wai-quantum: QIR and jeff read and written on every surface, each conversion checked, bounded against hostile input #554
128 changed files with 11985 additions and 184 deletions
174
.github/workflows/wai-quantum-formats.yml
vendored
Normal file
174
.github/workflows/wai-quantum-formats.yml
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
name: wai-quantum other formats
|
||||
|
||||
# The readers and writers of other formats (wai/wai-quantum/src/engine/formats/):
|
||||
# QIR under its base and adaptive profiles and jeff through the crate's own
|
||||
# Cap'n Proto reader and writer. Their unit tests (the wire format, the
|
||||
# OpenQASM they write, every intrinsic and gate held to its matrix, each
|
||||
# profile's refusals with their lines, the Pauli-product rotation against
|
||||
# exp(iθP), every prefix of a module refused), and the conformance set
|
||||
# (wai/quantum-conformance/formats/: the QIR specification's examples, the
|
||||
# jeff project's benchmarks and examples, hand-built modules and OpenQASM
|
||||
# sources written to each format, each with what the engine must do with it,
|
||||
# the QIR written pinned by its BLAKE3), and hostile inputs: every file
|
||||
# of the set mutated, each converted or refused with a code within its
|
||||
# bounds, natively and under wasm32-wasip2.
|
||||
#
|
||||
# The set runs natively, where a second test holds its bundle equal to its
|
||||
# files, and under wasm32-wasip2 by wasmtime, where the cases come from the
|
||||
# bundle the test compiles in and the QIR written must be the same bytes.
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/quantum-conformance/formats/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-formats.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/quantum-conformance/formats/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-formats.yml'
|
||||
|
||||
jobs:
|
||||
relevant:
|
||||
name: does this change touch it
|
||||
runs-on: linux-arm64
|
||||
outputs:
|
||||
run: ${{ steps.gate.outputs.run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: gate
|
||||
run: |
|
||||
set -euo pipefail
|
||||
r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-quantum-formats.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches the readers of other formats: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
native:
|
||||
name: readers, writers and the set · linux
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: linux
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Rust 1.98.0
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
command -v rustup >/dev/null 2>&1 || \
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
|
||||
rustup toolchain install 1.98.0 --profile minimal
|
||||
rustup default 1.98.0
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
# A module filter is satisfied by any one test of the module, so each
|
||||
# module's tests are required by name to have run.
|
||||
- name: The readers' and writers' unit tests
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --lib engine::formats 2>&1 | tee "$RUNNER_TEMP/formats.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$RUNNER_TEMP/formats.log" || { echo "::error::the formats' tests did not pass"; exit 1; }
|
||||
for m in engine::formats::capnp::tests engine::formats::emit::tests engine::formats::tests::every_gate_is_written_exactly engine::formats::tests::a_pauli_product_rotation_is_exp_i_theta_p engine::formats::tests::the_conformance_set_holds_these_modules engine::formats::tests::a_register_too_large_is_refused_before_it_is_allocated; do
|
||||
grep -q "^test $m.* \.\.\. ok$" "$RUNNER_TEMP/formats.log" || { echo "::error::no test of $m ran"; exit 1; }
|
||||
done
|
||||
- name: The conformance set
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --test formats_conformance 2>&1 | tee "$RUNNER_TEMP/set.log"
|
||||
grep -q 'test result: ok. 2 passed; 0 failed' "$RUNNER_TEMP/set.log" || { echo "::error::the conformance set did not pass"; exit 1; }
|
||||
# Hostile inputs: every file of the set mutated by a seeded generator
|
||||
# (bits flipped, files cut short and spliced, and every length, count,
|
||||
# offset and 32-bit field inflated), each converted or refused with a
|
||||
# code within its time and memory bounds. The count of inputs is pinned.
|
||||
- name: Hostile inputs
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --test formats_mutation -- --nocapture 2>&1 | tee "$RUNNER_TEMP/mutation.log"
|
||||
grep -q 'test result: ok. 1 passed; 0 failed' "$RUNNER_TEMP/mutation.log" || { echo "::error::a hostile input was not refused cleanly"; exit 1; }
|
||||
grep -q '45153 inputs: ' "$RUNNER_TEMP/mutation.log" || { echo "::error::the count of hostile inputs is not the pinned 45153"; exit 1; }
|
||||
- name: The readers without the receipts
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo check --locked --no-default-features --features quantum_engine --lib
|
||||
|
||||
wasip2:
|
||||
name: the set under wasm32-wasip2 (wasmtime)
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: linux
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Rust 1.98.0 with the wasm32-wasip2 target
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
command -v rustup >/dev/null 2>&1 || \
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
|
||||
rustup toolchain install 1.98.0 --profile minimal
|
||||
rustup default 1.98.0
|
||||
rustup target add --toolchain 1.98.0 wasm32-wasip2
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
# The release binary, pinned by version and SHA-256, rather than a build from source.
|
||||
- name: Install wasmtime 49.0.2
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
[ "$(uname -m)" = x86_64 ] || { echo "::error::the pinned wasmtime archive is x86_64; this host is $(uname -m)"; exit 1; }
|
||||
if ! command -v xz >/dev/null 2>&1; then
|
||||
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
|
||||
$SUDO apt-get update -qq
|
||||
$SUDO apt-get install -y -qq xz-utils
|
||||
fi
|
||||
v=49.0.2
|
||||
f="wasmtime-v$v-x86_64-linux.tar.xz"
|
||||
curl --proto '=https' --tlsv1.2 -sSfL -o "$RUNNER_TEMP/$f" \
|
||||
"https://github.com/bytecodealliance/wasmtime/releases/download/v$v/$f"
|
||||
echo "a4d6e9e3a5a60f527cf7793d674c48930c80c2e8977995b8a275cad3254b9322 $RUNNER_TEMP/$f" | sha256sum -c -
|
||||
tar -xJf "$RUNNER_TEMP/$f" -C "$RUNNER_TEMP"
|
||||
echo "$RUNNER_TEMP/wasmtime-v$v-x86_64-linux" >> "$GITHUB_PATH"
|
||||
# A debug build, so integer overflow panics instead of wrapping. The test
|
||||
# that reads the set's files has no wasip2 build; the one that runs the
|
||||
# cases from the compiled-in bundle does.
|
||||
- name: The conformance set under wasmtime
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
env:
|
||||
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --target wasm32-wasip2 --features full --test formats_conformance 2>&1 | tee "$RUNNER_TEMP/wasip2.log"
|
||||
grep -q 'test result: ok. 1 passed; 0 failed' "$RUNNER_TEMP/wasip2.log" || { echo "::error::the conformance set did not pass under wasip2"; exit 1; }
|
||||
# The same hostile inputs where an allocation larger than the address
|
||||
# space panics: a release build with overflow checks on, as it is slow
|
||||
# enough otherwise to outlast the job.
|
||||
- name: Hostile inputs under wasmtime
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
env:
|
||||
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
|
||||
CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS: "true"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --target wasm32-wasip2 --features full --test formats_mutation -- --nocapture 2>&1 | tee "$RUNNER_TEMP/wasip2-mutation.log"
|
||||
grep -q 'test result: ok. 1 passed; 0 failed' "$RUNNER_TEMP/wasip2-mutation.log" || { echo "::error::a hostile input was not refused cleanly under wasip2"; exit 1; }
|
||||
grep -q '45153 inputs: ' "$RUNNER_TEMP/wasip2-mutation.log" || { echo "::error::the count of hostile inputs under wasip2 is not the pinned 45153"; exit 1; }
|
||||
6
.github/workflows/wai-quantum-service.yml
vendored
6
.github/workflows/wai-quantum-service.yml
vendored
|
|
@ -108,7 +108,7 @@ jobs:
|
|||
key="$RUNNER_TEMP/service.key"; rm -f "$key" "$RUNNER_TEMP/service.keys.json"
|
||||
store="$RUNNER_TEMP/store"; rm -rf "$store"
|
||||
cargo build --locked --release
|
||||
WAI_QSVC_KEY="$key" WAI_QSVC_STORE="$store" WAI_QSVC_ADDR=127.0.0.1:18241 WAI_QSVC_BUDGET_GB=8 WAI_QSVC_JOB_GB=4 WAI_QSVC_WORKERS=2 \
|
||||
WAI_QSVC_KEY="$key" WAI_QSVC_STORE="$store" WAI_QSVC_ADDR=127.0.0.1:18241 WAI_QSVC_BUDGET_GB=8 WAI_QSVC_JOB_GB=4 WAI_QSVC_WORKERS=2 WAI_QSVC_CLIENT_BURST=60 \
|
||||
./target/release/wai-quantum-service serve 2> "$RUNNER_TEMP/service.log" &
|
||||
pid=$!
|
||||
trap 'kill $pid 2>/dev/null || true; cat "$RUNNER_TEMP/service.log"' EXIT
|
||||
|
|
@ -168,7 +168,7 @@ jobs:
|
|||
key="$RUNNER_TEMP/service.key"; rm -f "$key" "$RUNNER_TEMP/service.keys.json"
|
||||
store="$RUNNER_TEMP/store"; rm -rf "$store"
|
||||
cargo build --locked --release
|
||||
WAI_QSVC_KEY="$key" WAI_QSVC_STORE="$store" WAI_QSVC_ADDR=127.0.0.1:18241 WAI_QSVC_BUDGET_GB=8 WAI_QSVC_JOB_GB=4 WAI_QSVC_WORKERS=2 \
|
||||
WAI_QSVC_KEY="$key" WAI_QSVC_STORE="$store" WAI_QSVC_ADDR=127.0.0.1:18241 WAI_QSVC_BUDGET_GB=8 WAI_QSVC_JOB_GB=4 WAI_QSVC_WORKERS=2 WAI_QSVC_CLIENT_BURST=60 \
|
||||
./target/release/wai-quantum-service serve 2> "$RUNNER_TEMP/service.log" &
|
||||
pid=$!
|
||||
trap 'kill $pid 2>/dev/null || true; cat "$RUNNER_TEMP/service.log"' EXIT
|
||||
|
|
@ -224,7 +224,7 @@ jobs:
|
|||
export CARGO_TARGET_DIR="$HOME/hw-target/wai-quantum-service"
|
||||
nice -n 10 cargo build --locked --release
|
||||
t=$(mktemp -d)
|
||||
WAI_QSVC_KEY="$t/service.key" WAI_QSVC_STORE="$t/store" WAI_QSVC_ADDR=127.0.0.1:18244 WAI_QSVC_BUDGET_GB=4 WAI_QSVC_JOB_GB=2 WAI_QSVC_WORKERS=1 \
|
||||
WAI_QSVC_KEY="$t/service.key" WAI_QSVC_STORE="$t/store" WAI_QSVC_ADDR=127.0.0.1:18244 WAI_QSVC_BUDGET_GB=4 WAI_QSVC_JOB_GB=2 WAI_QSVC_WORKERS=1 WAI_QSVC_CLIENT_BURST=60 \
|
||||
"$CARGO_TARGET_DIR/release/wai-quantum-service" serve 2> "$t/service.log" &
|
||||
pid=$!
|
||||
trap 'kill $pid 2>/dev/null || true; cat "$t/service.log"; rm -rf "$t"' EXIT
|
||||
|
|
|
|||
1
.github/workflows/wai-quantum-studio.yml
vendored
1
.github/workflows/wai-quantum-studio.yml
vendored
|
|
@ -172,6 +172,7 @@ jobs:
|
|||
for t in an_update_is_held_to_this_build_s_key_and_the_version_it_was_signed_for only_a_copy_installed_by_its_own_installer_updates_itself the_updater_asks_the_release_s_manifest_and_requires_a_signed_version; do
|
||||
grep -q "^test tests::$t \.\.\. ok\$" "$RUNNER_TEMP/test.log" || { echo "::error::the update test $t did not run and pass"; exit 1; }
|
||||
done
|
||||
grep -q '^test tests::a_program_in_another_format_opens_in_the_app \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the formats test did not run and pass"; exit 1; }
|
||||
nice -n 10 cargo clippy --locked --release --all-targets -- -D warnings
|
||||
nice -n 10 cargo build --locked --release
|
||||
./target/release/wai-quantum-desktop check
|
||||
|
|
|
|||
17
.github/workflows/wai-web-wasm.yml
vendored
17
.github/workflows/wai-web-wasm.yml
vendored
|
|
@ -178,9 +178,10 @@ jobs:
|
|||
# engine_verdict, a repair there, the answer conformance set
|
||||
# (wai/quantum-conformance/answers/bundle.json) read to its codes, root and
|
||||
# order, its stored answers' receipts verified by running them again, a
|
||||
# course check whose bytes match the native build's pinned digest, and a
|
||||
# pulse run whose final density matrix is the native build's bits (its
|
||||
# pinned digest). The count is the four tests above and these fifteen.
|
||||
# course check whose bytes match the native build's pinned digest, a pulse
|
||||
# run whose final density matrix is the native build's bits (its pinned
|
||||
# digest), and a program converted between formats to the QIR bytes the
|
||||
# conformance set pins. The count is the four tests above and these sixteen.
|
||||
- name: The job engine in a page (wasm32 tests under Node)
|
||||
shell: bash
|
||||
working-directory: wai/wai-web
|
||||
|
|
@ -188,7 +189,7 @@ jobs:
|
|||
set -euo pipefail
|
||||
CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner \
|
||||
cargo test --locked --target wasm32-unknown-unknown --features quantum_engine 2>&1 | tee "$RUNNER_TEMP/wai-web-engine-wasm.log"
|
||||
grep -q "test result: ok. 19 passed; 0 failed" "$RUNNER_TEMP/wai-web-engine-wasm.log"
|
||||
grep -q "test result: ok. 20 passed; 0 failed" "$RUNNER_TEMP/wai-web-engine-wasm.log"
|
||||
# Its native half: the service's form and receipt, any angle on the state
|
||||
# vector, what does not run saying why, plan, lint, draw and methods as JSON,
|
||||
# critique, equivalence and variants as JSON, the classical shortcuts, the
|
||||
|
|
@ -204,15 +205,17 @@ jobs:
|
|||
# sealed there and worked out again, a repair held to the flagged
|
||||
# lines there, an answer in the answer view layer streamed in, its calls
|
||||
# run and its seal verified there, a correctness record and its corpus made
|
||||
# there, the circuits course read and checked there, and a pulse program's
|
||||
# schedule drawn, its run as a job to the pinned bits and its check there.
|
||||
# there, the circuits course read and checked there, a pulse program's
|
||||
# schedule drawn, its run as a job to the pinned bits and its check there,
|
||||
# and a program carried between OpenQASM, QIR and jeff there, each
|
||||
# conversion checked.
|
||||
- name: The job engine in a page (native unit tests)
|
||||
shell: bash
|
||||
working-directory: wai/wai-web
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --lib --features quantum_engine quantum_engine:: 2>&1 | tee "$RUNNER_TEMP/wai-web-engine.log"
|
||||
grep -q "test result: ok. 27 passed; 0 failed" "$RUNNER_TEMP/wai-web-engine.log"
|
||||
grep -q "test result: ok. 28 passed; 0 failed" "$RUNNER_TEMP/wai-web-engine.log"
|
||||
# The crate's native unit tests, run on the host: the pure-Rust halves of the
|
||||
# bindings, which wasm_tests does not run. They decode the committed integer
|
||||
# payloads to their sidecars' SHA-256 (int_payload::tests) and check that the
|
||||
|
|
|
|||
|
|
@ -178,6 +178,57 @@ wire format may change and such changes are recorded here.
|
|||
implementation, `channel_lineup_verify.py`, from the text alone, agrees on every vector, and a
|
||||
CI step runs both.
|
||||
|
||||
### wai-quantum: QIR under its profiles and jeff, read and written, every conversion checked
|
||||
|
||||
- **QIR** (`engine::formats::qir`): a module read as LLVM text, QIR 1.x (typed pointers) and 2.x (opaque pointers),
|
||||
under the profile its entry point names. Under the base profile a branch, a classical instruction, reading a result,
|
||||
or a gate or reset after a measurement is refused as what the profile forbids (`Q704`), on its line. Under the
|
||||
adaptive profile, measurements anywhere and forward branches on results (`__quantum__rt__read_result`, or QIR 1's
|
||||
`result_equal`) with the `i1` logic the profile allows are read as `if … else`, each branch to the block where its
|
||||
paths meet; an optional capability the module flags do not declare is forbidden, and one they declare that the reader
|
||||
does not take (loops, `switch`, `phi`, IR-defined functions, dynamic qubits or results, arrays) is refused as such
|
||||
(`Q705`). Integer and float computation the flags declare is computed on reading where its operands are constants.
|
||||
Rotations at any angle are read at their exact doubles, with a note (`Q709`) that the double-precision methods take
|
||||
them and the bit-exact method does not; a Clifford+T module stays on the bit-exact path. A program is written as QIR
|
||||
2.0: the base profile, or the adaptive one (forward branches on results with `read_result` and `br` alone) for a
|
||||
program that measures in the middle, resets or branches; Clifford+T is written as Clifford+T intrinsics and every
|
||||
angle as its exact hex double. The crate's bit-exact `quantum_qir` is unchanged.
|
||||
- **jeff** (`engine::formats::jeff`, format 0.3): read and written through a small Cap'n Proto reader and writer of
|
||||
the crate's own, with no dependency (segments, far pointers, every element size, each pointer bounds-checked, a limit
|
||||
on the words visited and the depth). The entry point's dataflow graph is run in an order its values allow: registers
|
||||
extracted, inserted, sliced, split and joined by index, `for` and `while` decided on reading unrolled, a `switch` on a
|
||||
measured bit read as a condition, calls inlined, classical values computed the same on every platform. Well-known
|
||||
gates take their controls after their targets, as the schema orders them; a Pauli-product rotation `exp(iθP)` is
|
||||
lowered exactly; a custom gate is read only by a standard gate's name (`Q711`). The writer gives one function, every
|
||||
gate well-known and exact with its global phase, the bits a returned array; a program that branches is refused
|
||||
(`Q720`).
|
||||
- **Codes** `Q700` to `Q721` in the reader's table (`docs/qasm-diagnostics.md`): every refusal names its place (a
|
||||
QIR line, a jeff function and operation). `docs/formats.md` says what each reader takes.
|
||||
- **Every surface:** `wai-quantum convert FILE --to qasm|qir|jeff [--profile] [-o] [--json]`, each conversion checked
|
||||
by reading the output back and holding it to the program with the equivalence ladder (a program that branches, step
|
||||
for step or by every outcome's probability); every verb reads `.ll`, `.qir` and `.jeff` files, or `--from`. Both MCP
|
||||
servers serve `convert_program` (`tools.v1.json#/$defs/convert`); the job service answers `POST /v1/convert`, and a
|
||||
job may carry `{"source": {"format", "program" | "program_base64"}}` in place of `qasm` (`job-request.v1.json`), as
|
||||
both MCP servers' run tools take it (`run_quantum_circuit`, `plan_quantum_circuit`, `run_on_target` and the dry run),
|
||||
one schema and one refusal; a request whose `qasm` is what its `source` reads to is read as it is.
|
||||
The Studio opens `.ll`, `.qir` and `.jeff` files through `engine_convert` (the desktop app through its `convert`
|
||||
command): the program goes into the editor as OpenQASM 3, with the format, the check and each note under it, and a
|
||||
refusal leaves the editor as it was with its code.
|
||||
- **Hostile input:** every size, count, index and bound a file gives is held to a cap before anything is made from
|
||||
it (a register's size before its qubits: a jeff register of 2^32 − 1 qubits is refused, `Q111`, where it once asked
|
||||
for 34 GB and trapped in a page); the wire reader bounds every pointer in 64 bits and counts each list element
|
||||
against the words it visits; the jeff reader counts every register slot, array element, call frame and condition
|
||||
term against one budget; the QIR reader bounds its branches' nesting, the instructions it runs over every path and
|
||||
the state each path copies; a condition is at most 1 024 terms and 32 deep once written. A conversion's check is
|
||||
not run past 262 144 gates applied or 4·10⁹ amplitudes, and says so. `tests/formats_mutation.rs` mutates every file
|
||||
of the conformance set from a fixed seed (45 153 inputs: bits flipped, files cut and spliced, every length, count,
|
||||
offset and 32-bit field inflated) and holds each to converting or a refusal with a code, within 20 s and 1 GiB,
|
||||
natively and under wasm32-wasip2 in `wai-quantum-formats.yml`.
|
||||
- **Conformance** (`wai/quantum-conformance/formats/`): the QIR specification's two examples, every intrinsic, a QIR 1
|
||||
module, each profile's refusals, hand-built jeff modules, the jeff project's own structured benchmarks and examples
|
||||
unchanged, and OpenQASM written to each format with the QIR bytes pinned, run natively and under wasm32-wasip2
|
||||
(`wai-quantum-formats.yml`). `wai-web-wasm.yml`'s pins move to 19 (wasm32) and 27 (native).
|
||||
|
||||
### wai-quantum: pulse and dynamics, simulated, the same bits everywhere, its receipts binding the calibrations
|
||||
|
||||
- **OpenPulse read** (`qasm::pulse`): a pulse program's `cal` and `defcal` blocks on physical qubits run in
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ The OpenQASM 3 reader's corpus, programs with what the reader must do with
|
|||
each, is `qasm3/`, with a README of its own. The error-correction text formats
|
||||
(noisy Clifford circuits and detector error models, read and written back byte
|
||||
for byte, with what each must count and what must be refused) are `qec-text/`,
|
||||
with a README of its own.
|
||||
with a README of its own. Programs in other formats (QIR under its profiles,
|
||||
and jeff), each with the program it must read to, its round trip and its
|
||||
refusals, and OpenQASM written to each, are `formats/`, with a README of its
|
||||
own.
|
||||
|
||||
An entry with no `capability` is a `wai.quantum.circuit` vector. The trees are the
|
||||
one reference all three surfaces are checked against, rather than being checked
|
||||
|
|
|
|||
63
wai/quantum-conformance/formats/README.md
Normal file
63
wai/quantum-conformance/formats/README.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Other formats: conformance
|
||||
|
||||
Programs in QIR and jeff, each with what the engine's readers and writers
|
||||
(`wai_quantum::engine::formats`, [docs](../../wai-quantum/docs/formats.md))
|
||||
must do with it: read it to the program a reference gives, give the outcomes
|
||||
it must give, write it back to its own format and read it again unchanged,
|
||||
or refuse it with a code and its place. OpenQASM sources are written to each
|
||||
format and read back.
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `qir/` | QIR modules: the specification's two example programs (the base profile's Bell pair and the adaptive profile's teleport chain, MIT, as the specification publishes its code), every intrinsic the reader takes, a Clifford+T module, a QIR 1 module with typed pointers from the crate's earlier writer, computation the module flags declare, and a module that names no profile. `*.ref.qasm` are the references, written by hand. |
|
||||
| `qir/refuse/` | A module for each thing a profile forbids, each capability declared and not taken, a stale read, an unknown intrinsic, a qubit past its count, an unknown profile, QIR 3, and text that is not LLVM: each with its code and line. |
|
||||
| `jeff/` | jeff modules built field by field from the schema (not by the writer): well-known gates with their controls after their targets, custom gates named as standard gates, a Pauli-product rotation; `refuse/` the refusals. A unit test (`engine::formats::tests::the_conformance_set_holds_these_modules`) makes them and holds the files to them. |
|
||||
| `jeff/upstream/` | The jeff project's own structured benchmarks (GHZ, QFT, QPE, Grover, teleportation, iterative QFT and QPE, multiplexer, QFT adders, a controlled modular multiplier: loops over registers, switches on measured bits, several segments) and its examples, unchanged (Apache-2.0), from the jeff repository at commit `97f73829caa2de0b6fbf925d1f97f9eb10c158ad`; the examples renamed by what they show. `*.ref.qasm` are references written by hand from each benchmark's source. Those the readers cannot hold exactly are refused with their codes. |
|
||||
| `qasm/` | OpenQASM sources written to QIR and jeff and read back: every gate of the language, Clifford+T, a branching program, a measurement in the middle with a reset, and timing neither format holds. The QIR written is pinned by its BLAKE3, the same bytes natively and under wasm32-wasip2. |
|
||||
| `manifest.json` | Each case: its file, its format, what it covers, its reference, and its expectations (the manifest's `expectations` says what each kind means). |
|
||||
| `bundle.json` | The manifest's cases with each file inline (text, or base64 for jeff), for builds that read no files. |
|
||||
|
||||
## Native
|
||||
|
||||
```sh
|
||||
cd wai/wai-quantum
|
||||
cargo test --release --features full --test formats_conformance
|
||||
cargo test --release --features full --lib engine::formats
|
||||
```
|
||||
|
||||
Two tests: every case against its expectations, and the bundle held equal to
|
||||
the files. After changing a file or the manifest, write the bundle:
|
||||
|
||||
```sh
|
||||
WAI_FORMATS_BUNDLE_WRITE=1 cargo test --release --features full --test formats_conformance the_bundle_is_the_corpus
|
||||
```
|
||||
|
||||
and after changing the hand-built jeff modules,
|
||||
`WAI_FORMATS_VECTORS_WRITE=1 cargo test --release --features full --lib the_conformance_set_holds_these_modules`.
|
||||
|
||||
The same files are the seed of the hostile-input test: every QIR and jeff
|
||||
file mutated (bits flipped, cut short, spliced with another, and every
|
||||
length, count, offset and 32-bit field inflated), 45 153 inputs from a fixed
|
||||
seed, each converted or refused with a code within 20 s and 1 GiB:
|
||||
|
||||
```sh
|
||||
cargo test --release --features full --test formats_mutation -- --nocapture
|
||||
```
|
||||
|
||||
## WASI (the edge)
|
||||
|
||||
```sh
|
||||
CARGO_TARGET_WASM32_WASIP2_RUNNER=wasmtime \
|
||||
cargo test --target wasm32-wasip2 --features full --test formats_conformance
|
||||
```
|
||||
|
||||
The cases come from the bundle compiled into the test. The hostile-input
|
||||
test runs there too, as a release build with overflow checks on:
|
||||
|
||||
```sh
|
||||
CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS=true CARGO_TARGET_WASM32_WASIP2_RUNNER=wasmtime \
|
||||
cargo test --release --target wasm32-wasip2 --features full --test formats_mutation
|
||||
```
|
||||
|
||||
CI: `wai-quantum-formats.yml` (the readers' and writers' unit tests, and the
|
||||
set natively and under wasm32-wasip2).
|
||||
718
wai/quantum-conformance/formats/bundle.json
Normal file
718
wai/quantum-conformance/formats/bundle.json
Normal file
File diff suppressed because one or more lines are too long
BIN
wai/quantum-conformance/formats/jeff/controls_after_targets.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/controls_after_targets.jeff
Normal file
Binary file not shown.
|
|
@ -0,0 +1,10 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[3] q;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
rx(-0.9) q[2];
|
||||
sdg q[0];
|
||||
U(0.2, 0.4, -0.6) q[1];
|
||||
ctrl(2) @ p(0.9) q[0], q[1], q[2];
|
||||
p(0.25) q[0];
|
||||
BIN
wai/quantum-conformance/formats/jeff/custom_named.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/custom_named.jeff
Normal file
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
rx(0.5) q[1];
|
||||
BIN
wai/quantum-conformance/formats/jeff/pauli_product.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/pauli_product.jeff
Normal file
Binary file not shown.
15
wai/quantum-conformance/formats/jeff/pauli_product.ref.qasm
Normal file
15
wai/quantum-conformance/formats/jeff/pauli_product.ref.qasm
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
// exp(0.37i X⊗Y⊗Z), with its parity carried along a chain rather than gathered on the last qubit.
|
||||
qubit[3] q;
|
||||
h q[0];
|
||||
sdg q[1];
|
||||
h q[1];
|
||||
cx q[0], q[1];
|
||||
cx q[1], q[2];
|
||||
rz(-0.74) q[2];
|
||||
cx q[1], q[2];
|
||||
cx q[0], q[1];
|
||||
h q[1];
|
||||
s q[1];
|
||||
h q[0];
|
||||
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/refuse/custom_unknown.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/refuse/custom_unknown.jeff
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/refuse/old_version.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/refuse/old_version.jeff
Normal file
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/refuse/qubit_twice.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/refuse/qubit_twice.jeff
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/refuse/truncated.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/refuse/truncated.jeff
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,11 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
// From the example's text: x on each qubit (custom X) with one control given after its target, as the schema orders a controlled gate's qubits: qubit k + 1 controls qubit k.
|
||||
qubit[5] q;
|
||||
bit[5] c;
|
||||
h q[0];
|
||||
cx q[1], q[0];
|
||||
cx q[2], q[1];
|
||||
cx q[3], q[2];
|
||||
cx q[4], q[3];
|
||||
c = measure q;
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
// From the example's text: two qubit arguments and one allocated; custom X, H, CX (control first, as its name says) and Rx.
|
||||
qubit[3] q;
|
||||
x q[0];
|
||||
h q[1];
|
||||
cx q[2], q[0];
|
||||
cx q[1], q[2];
|
||||
rx(0.5) q[0];
|
||||
Binary file not shown.
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/upstream/ghz-linear_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/ghz-linear_3.jeff
Normal file
Binary file not shown.
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
// From the benchmark's source: h on the first qubit, then each qubit controls x on the next.
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
cx q[1], q[2];
|
||||
c = measure q;
|
||||
BIN
wai/quantum-conformance/formats/jeff/upstream/ghz-star_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/ghz-star_3.jeff
Normal file
Binary file not shown.
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
// From the benchmark's source: h on the first qubit, which controls x on each other.
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
cx q[0], q[2];
|
||||
c = measure q;
|
||||
BIN
wai/quantum-conformance/formats/jeff/upstream/grover_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/grover_3.jeff
Normal file
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/upstream/iqft_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/iqft_3.jeff
Normal file
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/upstream/iqpe_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/iqpe_3.jeff
Normal file
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/upstream/multiplexer_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/multiplexer_3.jeff
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/upstream/qft_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/qft_3.jeff
Normal file
Binary file not shown.
14
wai/quantum-conformance/formats/jeff/upstream/qft_3.ref.qasm
Normal file
14
wai/quantum-conformance/formats/jeff/upstream/qft_3.ref.qasm
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
// From the benchmark's source: the textbook QFT on three qubits, qubit i measured into bit 2 - i.
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
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];
|
||||
c[2] = measure q[0];
|
||||
c[1] = measure q[1];
|
||||
c[0] = measure q[2];
|
||||
BIN
wai/quantum-conformance/formats/jeff/upstream/qpe_3.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/qpe_3.jeff
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/quantum-conformance/formats/jeff/upstream/teleportation.jeff
Normal file
BIN
wai/quantum-conformance/formats/jeff/upstream/teleportation.jeff
Normal file
Binary file not shown.
856
wai/quantum-conformance/formats/manifest.json
Normal file
856
wai/quantum-conformance/formats/manifest.json
Normal file
|
|
@ -0,0 +1,856 @@
|
|||
{
|
||||
"format": "wai.formats-conformance/1",
|
||||
"about": "Programs in other formats, each with what the engine must do with it: QIR modules (base and adaptive profiles) and jeff modules read, with the program each reads to and the refusals with their codes and places; OpenQASM sources written to each format and read back. jeff/upstream/ holds the jeff project's own structured benchmarks and examples, unchanged (Apache-2.0); the QIR specification's two example programs are its own (MIT).",
|
||||
"expectations": {
|
||||
"refused": "reading refuses the module with this code; `line` is the QIR line it names, `at` a phrase of where in a jeff module (a function and an operation)",
|
||||
"notes": "the codes of every warning and note the reader gives, sorted (none when empty)",
|
||||
"profile": "the QIR profile it is read under",
|
||||
"dynamic": "whether the program read measures in the middle, resets or branches",
|
||||
"qubits": "the qubits of the program read",
|
||||
"reference": "(beside expect) an OpenQASM program the reading must be the same circuit as, by the equivalence ladder; `how` the check that must decide it",
|
||||
"exact": "the bit-exact method takes the program read",
|
||||
"outcomes": "the outcomes 512 shots give (seed 7), every one of them and no other",
|
||||
"equal_bits": "pairs of bits equal in every outcome",
|
||||
"round_trip": "written back to its format and read again, the two readings the same by the ladder (or by every outcome's probability, for a program that branches)",
|
||||
"writes": "converted to each format named, the output read back and held to the program: the same (`how` the check that decides it), under a `profile`, with these `notes`, its bytes' BLAKE3 for QIR, or `refused` with a code (`profile_asked` asks for a profile)"
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"file": "qir/bell_base.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"the base profile's own example",
|
||||
"output records with labels"
|
||||
],
|
||||
"reference": "qir/bell.ref.qasm",
|
||||
"expect": {
|
||||
"profile": "base",
|
||||
"notes": [],
|
||||
"how": "tableau",
|
||||
"outcomes": [
|
||||
"00",
|
||||
"11"
|
||||
],
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/every_intrinsic.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"every intrinsic the reader takes",
|
||||
"angles in decimal, with an exponent and in hex",
|
||||
"__adj forms"
|
||||
],
|
||||
"reference": "qir/every_intrinsic.ref.qasm",
|
||||
"expect": {
|
||||
"profile": "base",
|
||||
"notes": [
|
||||
"Q709"
|
||||
],
|
||||
"how": "exact",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/clifford_t.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a Clifford+T module on the bit-exact method",
|
||||
"pi/4 as its exact hex double"
|
||||
],
|
||||
"reference": "qir/clifford_t.ref.qasm",
|
||||
"expect": {
|
||||
"profile": "base",
|
||||
"notes": [],
|
||||
"how": "exact",
|
||||
"exact": true,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/qft3_typed.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"QIR 1.0 with typed pointers, from the crate's earlier writer",
|
||||
"controlled phases as rz and cnot"
|
||||
],
|
||||
"reference": "qir/qft3_typed.ref.qasm",
|
||||
"expect": {
|
||||
"profile": "base",
|
||||
"notes": [],
|
||||
"how": "exact",
|
||||
"exact": true,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/teleport_chain.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"the adaptive profile's own example",
|
||||
"measurements in the middle, resets, forward branches on results"
|
||||
],
|
||||
"expect": {
|
||||
"profile": "adaptive",
|
||||
"notes": [],
|
||||
"dynamic": true,
|
||||
"qubits": 6,
|
||||
"equal_bits": [
|
||||
[
|
||||
4,
|
||||
5
|
||||
]
|
||||
],
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/computed.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"float computation the flags declare, computed on reading",
|
||||
"i1 logic on results as a condition"
|
||||
],
|
||||
"expect": {
|
||||
"profile": "adaptive",
|
||||
"notes": [
|
||||
"Q709"
|
||||
],
|
||||
"dynamic": true,
|
||||
"outcomes": [
|
||||
"001",
|
||||
"010",
|
||||
"100",
|
||||
"111"
|
||||
],
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/no_profile.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a module that names no profile"
|
||||
],
|
||||
"expect": {
|
||||
"profile": "base",
|
||||
"notes": [
|
||||
"Q702"
|
||||
],
|
||||
"outcomes": [
|
||||
"0",
|
||||
"1"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/base_branch.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"reading a result under the base profile"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q704",
|
||||
"line": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/base_gate_after_measure.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a gate after a measurement under the base profile"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q704",
|
||||
"line": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/undeclared_float.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"float computation without its module flag"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q704",
|
||||
"line": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/loop_undeclared.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a loop without backwards_branching"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q704",
|
||||
"line": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/loop_declared.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a loop, declared"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q705",
|
||||
"line": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/switch_declared.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"switch, declared"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q705",
|
||||
"line": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/dynamic_qubits.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"dynamic qubit management, declared"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q705",
|
||||
"line": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/stale_read.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a result read, measured again, then branched on"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q708",
|
||||
"line": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/unknown_intrinsic.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"an intrinsic the reader does not know"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q706",
|
||||
"line": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/qubit_past_count.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a qubit past required_num_qubits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q707",
|
||||
"line": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/unknown_profile.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"a profile the reader does not take"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q703",
|
||||
"line": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/major_version.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"QIR 3"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q701"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qir/refuse/not_llvm.ll",
|
||||
"format": "qir",
|
||||
"covers": [
|
||||
"not LLVM text"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q700"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/controls_after_targets.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"well-known gates, controls after targets as the schema orders them",
|
||||
"adjoint and power",
|
||||
"r1, u and gphase under a control"
|
||||
],
|
||||
"reference": "jeff/controls_after_targets.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q709"
|
||||
],
|
||||
"how": "exact",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/custom_named.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"custom gates named as standard gates"
|
||||
],
|
||||
"reference": "jeff/custom_named.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q709",
|
||||
"Q711"
|
||||
],
|
||||
"how": "exact",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/pauli_product.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a Pauli-product rotation exp(iθP) on three qubits"
|
||||
],
|
||||
"reference": "jeff/pauli_product.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q709",
|
||||
"Q712"
|
||||
],
|
||||
"how": "exact",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/custom_unknown.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a custom gate the library does not name"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q710",
|
||||
"at": "operation 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/custom_wrong_qubits.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a library name with the wrong qubits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q710",
|
||||
"at": "operation 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/qubit_twice.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a qubit used twice"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q713",
|
||||
"at": "operation 2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/old_version.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"jeff 0.1"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q701"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/angle_from_measurement.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"an angle computed from a measured bit"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q714",
|
||||
"at": "operation 4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/truncated.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a module cut short"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q700"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/refuse/register_too_large.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a register of 2^32 - 1 qubits, refused before it is allocated"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q111",
|
||||
"at": "operation 1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/ghz-linear_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a for loop over a register's indices, unrolled",
|
||||
"bits returned as an array"
|
||||
],
|
||||
"reference": "jeff/upstream/ghz-linear_3.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"how": "tableau",
|
||||
"outcomes": [
|
||||
"000",
|
||||
"111"
|
||||
],
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/ghz-star_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a for loop, unrolled"
|
||||
],
|
||||
"reference": "jeff/upstream/ghz-star_3.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"how": "tableau",
|
||||
"outcomes": [
|
||||
"000",
|
||||
"111"
|
||||
],
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/qft_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"nested loops with an angle carried as loop state",
|
||||
"bits returned in reverse order"
|
||||
],
|
||||
"reference": "jeff/upstream/qft_3.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"how": "exact",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/grover_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"Grover's search on two qubits, one iteration"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"outcomes": [
|
||||
"11"
|
||||
],
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/teleportation.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a switch on a measured bit, written as a condition",
|
||||
"written to QIR's adaptive profile; jeff writes no branch"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": true,
|
||||
"outcomes": [
|
||||
"000",
|
||||
"010",
|
||||
"100",
|
||||
"110"
|
||||
],
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "adaptive",
|
||||
"notes": [
|
||||
"Q715"
|
||||
]
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"refused": "Q720"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/iqft_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a qubit reused after a measurement and a reset",
|
||||
"switches on measured bits",
|
||||
"written to QIR's adaptive profile; jeff writes no branch"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": true,
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "adaptive",
|
||||
"notes": [
|
||||
"Q715"
|
||||
]
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"refused": "Q720"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/iqpe_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a qubit reused after a measurement and a reset",
|
||||
"switches on measured bits",
|
||||
"written to QIR's adaptive profile; jeff writes no branch"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": true,
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "adaptive",
|
||||
"notes": [
|
||||
"Q715"
|
||||
]
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"refused": "Q720"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/qpe_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"structured loops and registers, read and written back"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": false,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/multiplexer_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"structured loops and registers, read and written back"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": false,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/qft-adder-classical_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"structured loops and registers, read and written back"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": false,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/qft-adder-quantum_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"structured loops and registers, read and written back"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": false,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/controlled-multiplication-modulo-n_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"structured loops and registers, read and written back"
|
||||
],
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q715"
|
||||
],
|
||||
"dynamic": false,
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/repeat-until-success_3.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a while loop on a measurement"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q714",
|
||||
"at": "operation 10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/example-entangled-qubits.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"custom gates named as standard gates, a control given after its target"
|
||||
],
|
||||
"reference": "jeff/upstream/example-entangled-qubits.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q711"
|
||||
],
|
||||
"how": "tableau",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/example-qubits.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"an entry point that takes qubits"
|
||||
],
|
||||
"reference": "jeff/upstream/example-qubits.ref.qasm",
|
||||
"expect": {
|
||||
"notes": [
|
||||
"Q709",
|
||||
"Q711",
|
||||
"Q716"
|
||||
],
|
||||
"how": "exact",
|
||||
"round_trip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/example-entangled-calls.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"arithmetic on measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q714",
|
||||
"at": "operation 29"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/example-optimisation.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"an entry point that takes a classical argument"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q714"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/example-rewrite.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a register's slot extracted twice"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q713",
|
||||
"at": "operation 5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "jeff/upstream/example-simple.jeff",
|
||||
"format": "jeff",
|
||||
"covers": [
|
||||
"a custom gate the library does not name"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q710",
|
||||
"at": "operation 5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qasm/every_gate.qasm",
|
||||
"format": "qasm",
|
||||
"covers": [
|
||||
"every gate of the language, written to each format"
|
||||
],
|
||||
"expect": {
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "base",
|
||||
"how": "exact",
|
||||
"blake3": "1ec96352d855778f5a41c09d96fd0d260632663f03213e225255f074e8a4c022"
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qasm/clifford_t.qasm",
|
||||
"format": "qasm",
|
||||
"covers": [
|
||||
"Clifford+T written as Clifford+T intrinsics"
|
||||
],
|
||||
"expect": {
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "base",
|
||||
"how": "exact",
|
||||
"blake3": "967659b446471c62697f49df341972a45f47bef59d3b2fe26bfefc6670f6a50d"
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qasm/teleport.qasm",
|
||||
"format": "qasm",
|
||||
"covers": [
|
||||
"a branching program under the adaptive profile",
|
||||
"jeff writes no branch"
|
||||
],
|
||||
"expect": {
|
||||
"dynamic": true,
|
||||
"outcomes": [
|
||||
"100",
|
||||
"101",
|
||||
"110",
|
||||
"111"
|
||||
],
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "adaptive",
|
||||
"blake3": "4ac7bea67cb849aac1093b126a2da4a1edc5240176b6d0f42579760713d3c36f"
|
||||
},
|
||||
{
|
||||
"to": "qir",
|
||||
"profile_asked": "base",
|
||||
"refused": "Q720"
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"refused": "Q720"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qasm/measure_reset.qasm",
|
||||
"format": "qasm",
|
||||
"covers": [
|
||||
"a measurement in the middle and a reset"
|
||||
],
|
||||
"expect": {
|
||||
"dynamic": true,
|
||||
"outcomes": [
|
||||
"010",
|
||||
"111"
|
||||
],
|
||||
"writes": [
|
||||
{
|
||||
"to": "jeff"
|
||||
},
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "adaptive",
|
||||
"blake3": "fcb9b8d9517b3e76ae4f0a800222ca1624cc59d6a594f51781515d661bd169c2"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "qasm/timing.qasm",
|
||||
"format": "qasm",
|
||||
"covers": [
|
||||
"timing each format leaves out, and says so"
|
||||
],
|
||||
"expect": {
|
||||
"outcomes": [
|
||||
"00",
|
||||
"11"
|
||||
],
|
||||
"writes": [
|
||||
{
|
||||
"to": "qir",
|
||||
"profile": "base",
|
||||
"notes": [
|
||||
"Q721"
|
||||
]
|
||||
},
|
||||
{
|
||||
"to": "jeff",
|
||||
"notes": [
|
||||
"Q721"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
14
wai/quantum-conformance/formats/qasm/clifford_t.qasm
Normal file
14
wai/quantum-conformance/formats/qasm/clifford_t.qasm
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// A Clifford+T program: written to QIR in Clifford+T intrinsics alone, no
|
||||
// rotation, and read back to the bit-exact method.
|
||||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
h q[0];
|
||||
t q[0];
|
||||
p(pi/4) q[1];
|
||||
p(3*pi/4) q[2];
|
||||
cx q[0], q[1];
|
||||
ccx q[0], q[1], q[2];
|
||||
s q[2];
|
||||
c = measure q;
|
||||
17
wai/quantum-conformance/formats/qasm/every_gate.qasm
Normal file
17
wai/quantum-conformance/formats/qasm/every_gate.qasm
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Every gate of the language once, on qubits put in superpositions first,
|
||||
// then every qubit measured: written to QIR and jeff, each read back the same
|
||||
// circuit.
|
||||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
h q[0];
|
||||
ry(0.37) q[1];
|
||||
rx(1.1) q[2];
|
||||
id q[0]; x q[0]; y q[1]; z q[2]; h q[0]; s q[1]; sdg q[2]; t q[0]; tdg q[1]; sx q[2]; sxdg q[0];
|
||||
rx(0.3) q[0]; ry(-0.7) q[1]; rz(1.9) q[2]; p(0.45) q[0]; p(pi/4) q[1]; p(-pi/2) q[2]; U(0.2, 0.9, -1.4) q[1];
|
||||
cx q[0], q[1]; cy q[1], q[2]; cz q[2], q[0]; ch q[0], q[2]; cp(0.8) q[1], q[0];
|
||||
crx(0.6) q[0], q[1]; cry(-1.2) q[2], q[1]; crz(2.2) q[1], q[2]; cu(0.3, 0.4, 0.5, 0.6) q[0], q[2];
|
||||
swap q[0], q[2]; iswap q[1], q[0]; rxx(0.7) q[0], q[1]; ryy(1.1) q[1], q[2]; rzz(-0.4) q[2], q[0];
|
||||
ccx q[0], q[1], q[2]; ccz q[2], q[0], q[1]; cswap q[1], q[0], q[2];
|
||||
c = measure q;
|
||||
13
wai/quantum-conformance/formats/qasm/measure_reset.qasm
Normal file
13
wai/quantum-conformance/formats/qasm/measure_reset.qasm
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// A measurement in the middle and a reset, with no branch: written to jeff
|
||||
// with measureNd and reset, and to QIR under the adaptive profile.
|
||||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[3] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
c[0] = measure q[0];
|
||||
reset q[0];
|
||||
x q[0];
|
||||
c[1] = measure q[0];
|
||||
c[2] = measure q[1];
|
||||
20
wai/quantum-conformance/formats/qasm/teleport.qasm
Normal file
20
wai/quantum-conformance/formats/qasm/teleport.qasm
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Teleportation of |1>, corrected on what was measured: written to QIR under
|
||||
// the adaptive profile, every shot reads 1 on c[2]. jeff writes no branch.
|
||||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
x q[0];
|
||||
h q[1];
|
||||
cx q[1], q[2];
|
||||
cx q[0], q[1];
|
||||
h q[0];
|
||||
c[0] = measure q[0];
|
||||
c[1] = measure q[1];
|
||||
if (c[1]) {
|
||||
x q[2];
|
||||
}
|
||||
if (c[0] == 1) {
|
||||
z q[2];
|
||||
}
|
||||
c[2] = measure q[2];
|
||||
11
wai/quantum-conformance/formats/qasm/timing.qasm
Normal file
11
wai/quantum-conformance/formats/qasm/timing.qasm
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// A barrier and a delay: neither format has a place for them, so they are
|
||||
// left out, and the conversion says so.
|
||||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[2] c;
|
||||
h q[0];
|
||||
barrier q;
|
||||
delay[20ns] q[1];
|
||||
cx q[0], q[1];
|
||||
c = measure q;
|
||||
7
wai/quantum-conformance/formats/qir/bell.ref.qasm
Normal file
7
wai/quantum-conformance/formats/qir/bell.ref.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[2] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
c = measure q;
|
||||
52
wai/quantum-conformance/formats/qir/bell_base.ll
Normal file
52
wai/quantum-conformance/formats/qir/bell_base.ll
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
; The base profile's own example program (the QIR specification, MIT): two
|
||||
; qubits entangled, measured, and a tuple of the two results recorded.
|
||||
|
||||
@0 = internal constant [3 x i8] c"r1\00"
|
||||
@1 = internal constant [3 x i8] c"r2\00"
|
||||
@2 = internal constant [3 x i8] c"t0\00"
|
||||
|
||||
define i64 @Entry_Point_Name() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
|
||||
body: ; preds = %entry
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
call void @__quantum__qis__cnot__body(ptr null, ptr inttoptr (i64 1 to ptr))
|
||||
br label %measurements
|
||||
|
||||
measurements: ; preds = %body
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly inttoptr (i64 1 to ptr))
|
||||
br label %output
|
||||
|
||||
output: ; preds = %measurements
|
||||
call void @__quantum__rt__tuple_record_output(i64 2, ptr @2)
|
||||
call void @__quantum__rt__result_record_output(ptr null, ptr @0)
|
||||
call void @__quantum__rt__result_record_output(ptr inttoptr (i64 1 to ptr), ptr @1)
|
||||
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
declare void @__quantum__qis__h__body(ptr)
|
||||
|
||||
declare void @__quantum__qis__cnot__body(ptr, ptr)
|
||||
|
||||
declare void @__quantum__qis__mz__body(ptr, ptr writeonly) #1
|
||||
|
||||
declare void @__quantum__rt__initialize(ptr)
|
||||
|
||||
declare void @__quantum__rt__tuple_record_output(i64, ptr)
|
||||
|
||||
declare void @__quantum__rt__result_record_output(ptr, ptr)
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="schema_id" "required_num_qubits"="2" "required_num_results"="2" }
|
||||
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 0}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
30
wai/quantum-conformance/formats/qir/clifford_t.ll
Normal file
30
wai/quantum-conformance/formats/qir/clifford_t.ll
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
; A Clifford+T module, one rotation by exactly pi/4 in hex: it reads with no note and runs on the bit-exact method.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
call void @__quantum__qis__t__body(ptr null)
|
||||
call void @__quantum__qis__cx__body(ptr null, ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__s__adj(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__h__body(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__rz__body(double 0x3FE921FB54442D18, ptr inttoptr (i64 1 to ptr))
|
||||
br label %measurements
|
||||
measurements:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null) #1
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly inttoptr (i64 1 to ptr)) #1
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="2" "required_num_results"="2" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
11
wai/quantum-conformance/formats/qir/clifford_t.ref.qasm
Normal file
11
wai/quantum-conformance/formats/qir/clifford_t.ref.qasm
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[2] c;
|
||||
h q[0];
|
||||
t q[0];
|
||||
cx q[0], q[1];
|
||||
sdg q[1];
|
||||
h q[1];
|
||||
rz(pi/4) q[1];
|
||||
c = measure q;
|
||||
35
wai/quantum-conformance/formats/qir/computed.ll
Normal file
35
wai/quantum-conformance/formats/qir/computed.ll
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
; Adaptive: an angle computed from constants under float_computations, and a branch on two results combined by i1 logic: result 2 is 1 exactly when results 0 and 1 agree.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
%a = fadd double 0.25, 0.5
|
||||
%b = fmul double %a, 2.0
|
||||
call void @__quantum__qis__ry__body(double %b, ptr null)
|
||||
call void @__quantum__qis__h__body(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly inttoptr (i64 1 to ptr))
|
||||
%r0 = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
%r1 = call i1 @__quantum__rt__read_result(ptr readonly inttoptr (i64 1 to ptr))
|
||||
%x = xor i1 %r0, %r1
|
||||
%n = xor i1 %x, true
|
||||
br i1 %n, label %same, label %out
|
||||
same:
|
||||
call void @__quantum__qis__x__body(ptr inttoptr (i64 2 to ptr))
|
||||
br label %out
|
||||
out:
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 2 to ptr), ptr writeonly inttoptr (i64 2 to ptr))
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="3" "required_num_results"="3" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
!4 = !{i32 5, !"float_computations", !10}
|
||||
!5 = !{i32 1, !"backwards_branching", i2 0}
|
||||
!10 = !{!"double"}
|
||||
51
wai/quantum-conformance/formats/qir/every_intrinsic.ll
Normal file
51
wai/quantum-conformance/formats/qir/every_intrinsic.ll
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
; Every intrinsic the reader takes, once each, at angles that are not dyadic where an intrinsic takes one (decimal, exponent and hex), then every qubit measured.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
call void @__quantum__qis__h__body(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__h__body(ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__x__body(ptr null)
|
||||
call void @__quantum__qis__y__body(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__z__body(ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__s__body(ptr null)
|
||||
call void @__quantum__qis__s__adj(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__t__body(ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__t__adj(ptr null)
|
||||
call void @__quantum__qis__sx__body(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__rx__body(double 3.000000e-01, ptr null)
|
||||
call void @__quantum__qis__ry__body(double 0xBFF199999999999A, ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__rz__body(double 2.5, ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__rz__adj(double 0.7, ptr null)
|
||||
call void @__quantum__qis__r1__body(double 0.9, ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__cnot__body(ptr null, ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__cx__body(ptr inttoptr (i64 1 to ptr), ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__cy__body(ptr inttoptr (i64 2 to ptr), ptr null)
|
||||
call void @__quantum__qis__cz__body(ptr null, ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__swap__body(ptr inttoptr (i64 1 to ptr), ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__ccx__body(ptr null, ptr inttoptr (i64 1 to ptr), ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__ccz__body(ptr inttoptr (i64 2 to ptr), ptr inttoptr (i64 1 to ptr), ptr null)
|
||||
call void @__quantum__qis__rxx__body(double 0.4, ptr null, ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__ryy__body(double -0.6, ptr inttoptr (i64 1 to ptr), ptr inttoptr (i64 2 to ptr))
|
||||
call void @__quantum__qis__rzz__body(double 1.3, ptr inttoptr (i64 2 to ptr), ptr null)
|
||||
br label %measurements
|
||||
measurements:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null) #1
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly inttoptr (i64 1 to ptr)) #1
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 2 to ptr), ptr writeonly inttoptr (i64 2 to ptr)) #1
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="3" "required_num_results"="3" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
10
wai/quantum-conformance/formats/qir/every_intrinsic.ref.qasm
Normal file
10
wai/quantum-conformance/formats/qir/every_intrinsic.ref.qasm
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
h q[0]; h q[1]; h q[2];
|
||||
x q[0]; y q[1]; z q[2]; s q[0]; sdg q[1]; t q[2]; tdg q[0]; sx q[1];
|
||||
rx(0.3) q[0]; ry(-1.1) q[1]; rz(2.5) q[2]; rz(-0.7) q[0]; p(0.9) q[1];
|
||||
cx q[0], q[1]; cx q[1], q[2]; cy q[2], q[0]; cz q[0], q[2]; swap q[1], q[2]; ccx q[0], q[1], q[2]; ctrl(2) @ z q[2], q[1], q[0];
|
||||
rxx(0.4) q[0], q[1]; ryy(-0.6) q[1], q[2]; rzz(1.3) q[2], q[0];
|
||||
c = measure q;
|
||||
24
wai/quantum-conformance/formats/qir/no_profile.ll
Normal file
24
wai/quantum-conformance/formats/qir/no_profile.ll
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; A module that names no profile: read under the profile its instructions need (base), and said so.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
br label %measurements
|
||||
measurements:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null) #1
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
51
wai/quantum-conformance/formats/qir/qft3_typed.ll
Normal file
51
wai/quantum-conformance/formats/qir/qft3_typed.ll
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
; QIR emitted by wai-quantum — deterministic, byte-identical on every target.
|
||||
source_filename = "wai_quantum"
|
||||
|
||||
%Qubit = type opaque
|
||||
%Result = type opaque
|
||||
|
||||
declare void @__quantum__qis__h__body(%Qubit*)
|
||||
declare void @__quantum__qis__rz__body(double, %Qubit*)
|
||||
declare void @__quantum__qis__cnot__body(%Qubit*, %Qubit*)
|
||||
declare void @__quantum__qis__mz__body(%Qubit*, %Result*)
|
||||
declare void @__quantum__rt__result_record_output(%Result*, i8*)
|
||||
|
||||
define void @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0x3FE921FB54442D18, %Qubit* inttoptr (i64 1 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0xBFE921FB54442D18, %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0x3FE921FB54442D18, %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0x3FD921FB54442D18, %Qubit* inttoptr (i64 2 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0xBFD921FB54442D18, %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0x3FD921FB54442D18, %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0x3FE921FB54442D18, %Qubit* inttoptr (i64 2 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0xBFE921FB54442D18, %Qubit* inttoptr (i64 1 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
|
||||
call void @__quantum__qis__rz__body(double 0x3FE921FB54442D18, %Qubit* inttoptr (i64 1 to %Qubit*))
|
||||
call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
|
||||
call void @__quantum__qis__cnot__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 2 to %Qubit*))
|
||||
call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
|
||||
call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
|
||||
call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 2 to %Result*))
|
||||
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
|
||||
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
|
||||
call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 2 to %Result*), i8* null)
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="3" "required_num_results"="3" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 1}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 0}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
12
wai/quantum-conformance/formats/qir/qft3_typed.ref.qasm
Normal file
12
wai/quantum-conformance/formats/qir/qft3_typed.ref.qasm
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[3] q;
|
||||
h q[0];
|
||||
cp(2*pi/4) q[1],q[0];
|
||||
cp(2*pi/8) q[2],q[0];
|
||||
h q[1];
|
||||
cp(2*pi/4) q[2],q[1];
|
||||
h q[2];
|
||||
cx q[0],q[2];
|
||||
cx q[2],q[0];
|
||||
cx q[0],q[2];
|
||||
25
wai/quantum-conformance/formats/qir/refuse/base_branch.ll
Normal file
25
wai/quantum-conformance/formats/qir/refuse/base_branch.ll
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
; Under the base profile, reading a result: forbidden.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
br label %measurements
|
||||
measurements:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null) #1
|
||||
%r = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
; Under the base profile, a gate on a qubit after its measurement: forbidden.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null) #1
|
||||
br label %measurements
|
||||
measurements:
|
||||
call void @__quantum__qis__x__body(ptr null)
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
18
wai/quantum-conformance/formats/qir/refuse/dynamic_qubits.ll
Normal file
18
wai/quantum-conformance/formats/qir/refuse/dynamic_qubits.ll
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
; A qubit allocated at run time, with dynamic qubit management declared: a capability this reader does not take.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
%q = call ptr @__quantum__rt__qubit_allocate()
|
||||
call void @__quantum__qis__h__body(ptr %q)
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="0" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 true}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
23
wai/quantum-conformance/formats/qir/refuse/loop_declared.ll
Normal file
23
wai/quantum-conformance/formats/qir/refuse/loop_declared.ll
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
; The same loop with backwards_branching declared: a capability this reader does not take.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %l
|
||||
l:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
%r = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
br i1 %r, label %l, label %done
|
||||
done:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3, !4}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
!4 = !{i32 1, !"backwards_branching", i2 2}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
; A loop (a branch back to an earlier block) with no backwards_branching flag: forbidden.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %l
|
||||
l:
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
%r = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
br i1 %r, label %l, label %done
|
||||
done:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
24
wai/quantum-conformance/formats/qir/refuse/major_version.ll
Normal file
24
wai/quantum-conformance/formats/qir/refuse/major_version.ll
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; A QIR major version the reader does not take.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
br label %measurements
|
||||
measurements:
|
||||
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="0" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 3}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
3
wai/quantum-conformance/formats/qir/refuse/not_llvm.ll
Normal file
3
wai/quantum-conformance/formats/qir/refuse/not_llvm.ll
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
; Not LLVM text: no function, no entry point.
|
||||
OPENQASM 3.0;
|
||||
qubit q;
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
; Qubit 4 in a module that declares one qubit.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr inttoptr (i64 4 to ptr))
|
||||
br label %measurements
|
||||
measurements:
|
||||
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="0" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
24
wai/quantum-conformance/formats/qir/refuse/stale_read.ll
Normal file
24
wai/quantum-conformance/formats/qir/refuse/stale_read.ll
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
; A result read, measured again into the same result, and only then branched on: the branch would read the later measurement.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
%r = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly null)
|
||||
br i1 %r, label %a, label %b
|
||||
a:
|
||||
call void @__quantum__qis__x__body(ptr inttoptr (i64 1 to ptr))
|
||||
br label %b
|
||||
b:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="2" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
; A switch on a result, multiple-target branching declared: a capability this reader does not take.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
%r = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
switch i1 %r, label %done [ i1 true, label %one ]
|
||||
one:
|
||||
call void @__quantum__qis__x__body(ptr null)
|
||||
br label %done
|
||||
done:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="1" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3, !4}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
!4 = !{i32 1, !"multiple_target_branching", i1 true}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
; The same computation with no float_computations flag: what the adaptive profile forbids, refused on its line.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
%a = fadd double 0.25, 0.5
|
||||
%b = fmul double %a, 2.0
|
||||
call void @__quantum__qis__ry__body(double %b, ptr null)
|
||||
call void @__quantum__qis__h__body(ptr inttoptr (i64 1 to ptr))
|
||||
call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 1 to ptr), ptr writeonly inttoptr (i64 1 to ptr))
|
||||
%r0 = call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
%r1 = call i1 @__quantum__rt__read_result(ptr readonly inttoptr (i64 1 to ptr))
|
||||
%x = xor i1 %r0, %r1
|
||||
%n = xor i1 %x, true
|
||||
br i1 %n, label %same, label %out
|
||||
same:
|
||||
call void @__quantum__qis__x__body(ptr inttoptr (i64 2 to ptr))
|
||||
br label %out
|
||||
out:
|
||||
call void @__quantum__qis__mz__body(ptr inttoptr (i64 2 to ptr), ptr writeonly inttoptr (i64 2 to ptr))
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="labels" "required_num_qubits"="3" "required_num_results"="3" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
; An intrinsic the reader does not know.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__foo__body(ptr null)
|
||||
br label %measurements
|
||||
measurements:
|
||||
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="base_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="0" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
; A profile the reader does not take.
|
||||
|
||||
define i64 @main() #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
body:
|
||||
call void @__quantum__qis__h__body(ptr null)
|
||||
br label %measurements
|
||||
measurements:
|
||||
|
||||
br label %output
|
||||
output:
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="custom_profile" "output_labeling_schema"="labels" "required_num_qubits"="1" "required_num_results"="0" }
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3}
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 1}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
121
wai/quantum-conformance/formats/qir/teleport_chain.ll
Normal file
121
wai/quantum-conformance/formats/qir/teleport_chain.ll
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
; The adaptive profile's own example program (the QIR specification, MIT): a
|
||||
; Bell pair whose second half is teleported twice, each step measuring in
|
||||
; the middle and correcting on the result. The pair ends between qubits 0 and
|
||||
; 5, so results 4 and 5 are equal on every shot.
|
||||
|
||||
@0 = internal constant [5 x i8] c"0_t0\00"
|
||||
@1 = internal constant [5 x i8] c"0_t1\00"
|
||||
|
||||
define i64 @TeleportChain() local_unnamed_addr #0 {
|
||||
entry:
|
||||
call void @__quantum__rt__initialize(ptr null)
|
||||
br label %body
|
||||
|
||||
body: ; preds = %entry
|
||||
tail call void @__quantum__qis__h__body(ptr null)
|
||||
tail call void @__quantum__qis__cnot__body(ptr null, ptr nonnull inttoptr (i64 1 to ptr))
|
||||
tail call void @__quantum__qis__h__body(ptr nonnull inttoptr (i64 2 to ptr))
|
||||
tail call void @__quantum__qis__cnot__body(ptr nonnull inttoptr (i64 2 to ptr), ptr nonnull inttoptr (i64 4 to ptr))
|
||||
tail call void @__quantum__qis__h__body(ptr nonnull inttoptr (i64 3 to ptr))
|
||||
tail call void @__quantum__qis__cnot__body(ptr nonnull inttoptr (i64 3 to ptr), ptr nonnull inttoptr (i64 5 to ptr))
|
||||
tail call void @__quantum__qis__cnot__body(ptr nonnull inttoptr (i64 1 to ptr), ptr nonnull inttoptr (i64 2 to ptr))
|
||||
tail call void @__quantum__qis__h__body(ptr nonnull inttoptr (i64 1 to ptr))
|
||||
tail call void @__quantum__qis__mz__body(ptr nonnull inttoptr (i64 1 to ptr), ptr writeonly null)
|
||||
tail call void @__quantum__qis__reset__body(ptr nonnull inttoptr (i64 1 to ptr))
|
||||
%0 = tail call i1 @__quantum__rt__read_result(ptr readonly null)
|
||||
br i1 %0, label %then__1, label %continue__1
|
||||
|
||||
; conditional quantum gate (only one in this block, but many can appear and the full quantum instruction set should be usable)
|
||||
then__1: ; preds = %body
|
||||
tail call void @__quantum__qis__z__body(ptr nonnull inttoptr (i64 4 to ptr))
|
||||
br label %continue__1
|
||||
|
||||
continue__1: ; preds = %then__1, %body
|
||||
tail call void @__quantum__qis__mz__body(ptr nonnull inttoptr (i64 2 to ptr), ptr writeonly nonnull inttoptr (i64 1 to ptr))
|
||||
tail call void @__quantum__qis__reset__body(ptr nonnull inttoptr (i64 2 to ptr))
|
||||
%1 = tail call i1 @__quantum__rt__read_result(ptr readonly nonnull inttoptr (i64 1 to ptr))
|
||||
br i1 %1, label %then__2, label %continue__2
|
||||
|
||||
then__2: ; preds = %continue__1
|
||||
tail call void @__quantum__qis__x__body(ptr nonnull inttoptr (i64 4 to ptr))
|
||||
br label %continue__2
|
||||
|
||||
continue__2: ; preds = %then__2, %continue__1
|
||||
tail call void @__quantum__qis__cnot__body(ptr nonnull inttoptr (i64 4 to ptr), ptr nonnull inttoptr (i64 3 to ptr))
|
||||
tail call void @__quantum__qis__h__body(ptr nonnull inttoptr (i64 4 to ptr))
|
||||
tail call void @__quantum__qis__mz__body(ptr nonnull inttoptr (i64 4 to ptr), ptr writeonly nonnull inttoptr (i64 2 to ptr))
|
||||
tail call void @__quantum__qis__reset__body(ptr nonnull inttoptr (i64 4 to ptr))
|
||||
%2 = tail call i1 @__quantum__rt__read_result(ptr readonly nonnull inttoptr (i64 2 to ptr))
|
||||
br i1 %2, label %then__3, label %continue__3
|
||||
|
||||
then__3: ; preds = %continue__2
|
||||
tail call void @__quantum__qis__z__body(ptr nonnull inttoptr (i64 5 to ptr))
|
||||
br label %continue__3
|
||||
|
||||
continue__3: ; preds = %then__3, %continue__2
|
||||
tail call void @__quantum__qis__mz__body(ptr nonnull inttoptr (i64 3 to ptr), ptr writeonly nonnull inttoptr (i64 3 to ptr))
|
||||
tail call void @__quantum__qis__reset__body(ptr nonnull inttoptr (i64 3 to ptr))
|
||||
%3 = tail call i1 @__quantum__rt__read_result(ptr readonly nonnull inttoptr (i64 3 to ptr))
|
||||
br i1 %3, label %then__4, label %continue__4
|
||||
|
||||
then__4: ; preds = %continue__3
|
||||
tail call void @__quantum__qis__x__body(ptr nonnull inttoptr (i64 5 to ptr))
|
||||
br label %continue__4
|
||||
|
||||
continue__4: ; preds = %continue__3, %then__4
|
||||
tail call void @__quantum__qis__mz__body(ptr null, ptr writeonly nonnull inttoptr (i64 4 to ptr))
|
||||
tail call void @__quantum__qis__reset__body(ptr null)
|
||||
tail call void @__quantum__qis__mz__body(ptr nonnull inttoptr (i64 5 to ptr), ptr writeonly nonnull inttoptr (i64 5 to ptr))
|
||||
tail call void @__quantum__qis__reset__body(ptr nonnull inttoptr (i64 5 to ptr))
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
call void @__quantum__rt__result_record_output(ptr nonnull inttoptr (i64 4 to ptr), ptr @0)
|
||||
call void @__quantum__rt__result_record_output(ptr nonnull inttoptr (i64 5 to ptr), ptr @1)
|
||||
ret i64 0
|
||||
}
|
||||
|
||||
; declarations of QIS functions
|
||||
|
||||
declare void @__quantum__qis__cnot__body(ptr, ptr) local_unnamed_addr
|
||||
|
||||
declare void @__quantum__qis__h__body(ptr) local_unnamed_addr
|
||||
|
||||
declare void @__quantum__qis__x__body(ptr) local_unnamed_addr
|
||||
|
||||
declare void @__quantum__qis__z__body(ptr) local_unnamed_addr
|
||||
|
||||
declare void @__quantum__qis__reset__body(ptr) local_unnamed_addr
|
||||
|
||||
declare void @__quantum__qis__mz__body(ptr, ptr writeonly) #1
|
||||
|
||||
; declarations of runtime functions
|
||||
|
||||
declare void @__quantum__rt__initialize(ptr)
|
||||
|
||||
declare i1 @__quantum__rt__read_result(ptr readonly)
|
||||
|
||||
declare void @__quantum__rt__result_record_output(ptr, ptr)
|
||||
|
||||
; attributes
|
||||
|
||||
attributes #0 = { "entry_point" "qir_profiles"="adaptive_profile" "output_labeling_schema"="schema_id" "required_num_qubits"="6" "required_num_results"="6" }
|
||||
|
||||
attributes #1 = { "irreversible" }
|
||||
|
||||
; module flags
|
||||
|
||||
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
|
||||
|
||||
!0 = !{i32 1, !"qir_major_version", i32 2}
|
||||
!1 = !{i32 7, !"qir_minor_version", i32 0}
|
||||
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
|
||||
!3 = !{i32 1, !"dynamic_result_management", i1 false}
|
||||
!4 = !{i32 5, !"int_computations", !10}
|
||||
!5 = !{i32 5, !"float_computations", !11}
|
||||
!6 = !{i32 1, !"ir_functions", i1 false}
|
||||
!7 = !{i32 1, !"backwards_branching", i2 0}
|
||||
!8 = !{i32 1, !"multiple_target_branching", i1 false}
|
||||
!9 = !{i32 1, !"multiple_return_points", i1 false}
|
||||
!10 = !{!"i32", !"i64"}
|
||||
!11 = !{!"float", !"double"}
|
||||
|
|
@ -65,6 +65,8 @@ The engine makes each edit in the program's own text, through its syntax tree, s
|
|||
|
||||
The diagram's description, which a screen reader reads, is the engine's account of the circuit: its qubits and bits, then each column, each gate with its role on each qubit, each measurement with its bit, and each condition as the legend writes it. "SVG" saves the drawing as the engine writes it, a standalone image that follows the colour of the text it is placed in, and "LaTeX" saves it as one picture in plain TikZ that needs only `\usepackage{tikz}`.
|
||||
|
||||
"Open" takes a program in OpenQASM, or in QIR (`.ll`, `.qir`) or jeff (`.jeff`), which the engine reads to OpenQASM 3 in the page (`engine_convert`; [the formats page](../wai-quantum/docs/formats.md)): the program goes into the editor, and the line under it names the format and its version, the check (the program written back to its format and read again) and each of the reader's notes with its code. A module the reader refuses leaves the editor as it was, and the status line gives the refusal with its code and its place.
|
||||
|
||||
## Device
|
||||
|
||||
Under **Device**, a device target: one of the built-in targets (synthetic, in the shapes of published formats), one imported here (**Import…** reads a calibration or target snapshot in any format the engine reads, kept in this browser), or, in the desktop app, one kept with `wai-quantum targets import`. The coupling map is drawn with each pair coloured by its two-qubit error and each qubit by its readout error, one-qubit error or T1. The colours are five bins of one hue, by quantile of the device's own values; the poorest pairs are drawn thicker, every mark gives its numbers on hover, and **As a table** lists them. With a device chosen, a run is compiled to its gates, placed on the qubits and routes most likely to succeed, and simulated under its noise; the noise fields wait, since the noise is the device's own. The layout the plan chose is drawn on the map before the run. The result's **Device** block names the target and its hash (in the receipt), the placement and its expected success beside the fewest swaps', the noise, and how far the counts are from the ideal ones. It is a model of the device, and it says so. On the service, a built-in target goes by name and any other as its document.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ Ctrl+Enter(macOS 上为 ⌘+Enter)运行程序,Escape 取消运行。程
|
|||
|
||||
线路图的描述(供屏幕阅读器朗读)是引擎对线路的叙述:先是其量子比特和比特,然后是每一列,每个门及其在每个量子比特上的角色,每次测量及其比特,以及按图例写法给出的每个条件。“SVG”按引擎写出的样子保存线路图,这是一张独立的图像,颜色随其所在位置的文字颜色而变;“LaTeX”则把它保存为一幅纯 TikZ 图,只需要 `\usepackage{tikz}`。
|
||||
|
||||
“打开”(Open)接受 OpenQASM 程序,也接受 QIR(`.ll`、`.qir`)或 jeff(`.jeff`)文件,由引擎在页面中读取为 OpenQASM 3(`engine_convert`;[格式说明页](../wai-quantum/docs/formats.md)):程序放入编辑器,其下的一行说明格式及其版本、检查结果(程序写回原格式后再读取一次)以及读取器的每条说明及其代码。读取器拒绝的模块不会改变编辑器中的内容,状态行给出拒绝原因及其代码和位置。
|
||||
|
||||
## 设备
|
||||
|
||||
在**设备**(Device)下选择一个设备目标:内置目标之一(合成的,采用已公开格式的形态)、在此导入的目标(**导入…**(Import…)读取引擎能读取的任何格式的校准快照或目标快照,保存在这个浏览器中),或者在桌面应用中,用 `wai-quantum targets import` 保存的目标。耦合图中,每个耦合对按其双量子比特门误差着色,每个量子比特按其读出误差、单量子比特门误差或 T1 着色。颜色为同一色调的五档,按该设备自身数值的分位数划分;最差的耦合对画得更粗,每个标记在悬停时给出其数值,**以表格显示**(As a table)则把它们列出。选定设备后,运行会被编译为该设备的门,放置到最可能成功的量子比特和路由上,并在其噪声下模拟;噪声字段暂不起作用,因为噪声取自设备本身。计划选定的布局会在运行之前画在耦合图上。结果中的**设备**区块列出目标及其哈希(写入回执)、放置方式及其预期成功率(与交换次数最少的放置方式的预期成功率并列)、噪声,以及计数与理想计数相差多少。这是设备的一个模型,结果也如此注明。在作业服务上,内置目标按名称传递,其他目标则以其文档传递。
|
||||
|
|
|
|||
|
|
@ -151,6 +151,9 @@
|
|||
"frame.fixed": "Fixed, as {version}. Undo brings the lines back.",
|
||||
"frame.saved_job": "Saved {name}. wai-quantum verify checks it.",
|
||||
"frame.opened": "Opened {name}.",
|
||||
"frame.opened_from": "Opened {name}, read from {format} as OpenQASM 3 (written back and checked: {check}). Notes: {notes}.",
|
||||
"frame.open_refused": "{name} does not read as {format}: {error}",
|
||||
"frame.no_notes": "none",
|
||||
"frame.copied": "Copied a link with the program in its fragment, which no server sees.",
|
||||
"frame.from_history": "From the history: run on {where}, {when}.",
|
||||
"frame.history_empty": "Jobs you run appear here, kept on this device.",
|
||||
|
|
|
|||
|
|
@ -151,6 +151,9 @@
|
|||
"frame.fixed": "已修正,记为 {version}。撤销即可恢复这些行。",
|
||||
"frame.saved_job": "已保存 {name}。可用 wai-quantum verify 检查它。",
|
||||
"frame.opened": "已打开 {name}。",
|
||||
"frame.opened_from": "已打开 {name},从 {format} 读取为 OpenQASM 3(写回后检查:{check})。说明:{notes}。",
|
||||
"frame.open_refused": "{name} 无法按 {format} 读取:{error}",
|
||||
"frame.no_notes": "无",
|
||||
"frame.copied": "已复制一个把程序放在片段中的链接,任何服务器都看不到它。",
|
||||
"frame.from_history": "来自历史:在{where}上运行,{when}。",
|
||||
"frame.history_empty": "你运行的作业会出现在这里,保存在这台设备上。",
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ export class TabEngine {
|
|||
verify(job) { return this.call('verify', { job }); }
|
||||
critique(qasm) { return this.call('critique', { qasm }); }
|
||||
equivalent(a, b) { return this.call('equivalent', { a, b }); }
|
||||
// A program carried between formats (engine::formats): {to, program | program_base64, from?} in, the
|
||||
// conversion (or its refusal as data, {error, code}) out.
|
||||
convert(request) { return this.call('convert', { request }); }
|
||||
variants(qasm) { return this.call('variants', { qasm }); }
|
||||
shortcuts(qasm, thorough = false) { return this.call('shortcuts', { qasm, thorough }); }
|
||||
// A compile ({qasm, epsilon, level, basis, stages}): sealed with this browser's key.
|
||||
|
|
@ -198,6 +201,8 @@ export class DesktopEngine {
|
|||
// A critique names a problem as {ok: false, error}, as a lint does.
|
||||
async critique(qasm) { return JSON.parse(await this.invoke('critique', { qasm })); }
|
||||
equivalent(a, b) { return this.call('equivalent', { a, b }); }
|
||||
// A refusal comes back as data ({error, code}), as the tab's does.
|
||||
async convert(request) { return JSON.parse(await this.invoke('convert', { request: JSON.stringify(request) })); }
|
||||
variants(qasm) { return this.call('variants', { qasm }); }
|
||||
shortcuts(qasm, thorough = false) { return this.call('shortcuts', { qasm, thorough }); }
|
||||
// A compile, sealed with this user's key.
|
||||
|
|
|
|||
|
|
@ -110,6 +110,13 @@ const handsField = StateField.define({
|
|||
});
|
||||
const handGutter = gutter({ class: 'qs-hand-gutter', markers: (v) => v.state.field(handsField), initialSpacer: () => new HandMark('spacer', '') });
|
||||
|
||||
// Bytes as standard base64, for a binary program sent to the engine.
|
||||
function toBase64(bytes) {
|
||||
let s = '';
|
||||
for (let i = 0; i < bytes.length; i += 0x8000) s += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
||||
return btoa(s);
|
||||
}
|
||||
|
||||
function mount(root) {
|
||||
const desktop = onDesktop();
|
||||
// A host page with a heading of its own mounts the Studio with data-embedded, and its name is not a second h1.
|
||||
|
|
@ -195,7 +202,7 @@ function mount(root) {
|
|||
|
||||
// ---- the program ----
|
||||
const lintBadge = el('span', { class: 'qs-badge', id: 'qs-lint', text: '…' });
|
||||
const fileIn = el('input', { type: 'file', accept: '.qasm,.txt,text/plain', hidden: true, 'aria-hidden': 'true' });
|
||||
const fileIn = el('input', { type: 'file', id: 'qs-open-file', accept: '.qasm,.ll,.qir,.jeff,.txt,text/plain', hidden: true, 'aria-hidden': 'true' });
|
||||
const shows = el('p', { class: 'qs-shows', id: 'qs-shows' });
|
||||
const reviewBox = el('div', { class: 'qs-review', id: 'qs-review', hidden: true, role: 'region', 'aria-label': tr('frame.review_label') });
|
||||
const editorHost = el('div', { class: 'qs-editor', id: 'qs-editor' });
|
||||
|
|
@ -823,9 +830,25 @@ function mount(root) {
|
|||
openBtn.addEventListener('click', () => fileIn.click());
|
||||
fileIn.addEventListener('change', async () => {
|
||||
const f = fileIn.files?.[0]; if (!f) return;
|
||||
const body = await f.text();
|
||||
if (await from(`the file ${f.name}`, () => setText(body))) shows.textContent = tr('frame.opened', { name: f.name });
|
||||
fileIn.value = '';
|
||||
// QIR and jeff are read by the engine to OpenQASM 3, with what it noted.
|
||||
const format = /\.(ll|qir)$/i.test(f.name) ? 'qir' : /\.jeff$/i.test(f.name) ? 'jeff' : null;
|
||||
if (!format) {
|
||||
const body = await f.text();
|
||||
if (await from(`the file ${f.name}`, () => setText(body))) shows.textContent = tr('frame.opened', { name: f.name });
|
||||
return;
|
||||
}
|
||||
let r;
|
||||
try {
|
||||
const request = { from: format, to: 'qasm' };
|
||||
if (format === 'jeff') request.program_base64 = toBase64(new Uint8Array(await f.arrayBuffer()));
|
||||
else request.program = await f.text();
|
||||
r = await local.convert(request);
|
||||
} catch (e) { r = { error: e.message }; }
|
||||
if (r.error) { setStatus(tr('frame.open_refused', { name: f.name, format: format === 'qir' ? 'QIR' : 'jeff', error: r.error }), 'bad'); return; }
|
||||
if (!(await from(`the file ${f.name}`, () => setText(r.program)))) return;
|
||||
const notes = (r.notes || []).map((n) => `${n.message} [${n.code}]`);
|
||||
shows.textContent = tr('frame.opened_from', { name: f.name, format: format === 'qir' ? `QIR ${r.read?.version ?? ''}`.trim() : `jeff ${r.read?.version ?? ''}`.trim(), check: r.check?.verdict?.verdict ?? 'unchecked', notes: notes.length ? notes.join('; ') : tr('frame.no_notes') });
|
||||
});
|
||||
shareBtn.addEventListener('click', () => {
|
||||
const u = new URL(location.href); u.hash = 'qasm=' + encodeURIComponent(text()); u.search = '';
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ self.onmessage = async (ev) => {
|
|||
case 'verify': text = mod.engine_verify(JSON.stringify(ev.data.job)); break;
|
||||
case 'critique': text = mod.engine_critique(ev.data.qasm); break;
|
||||
case 'equivalent': text = mod.engine_equivalent(ev.data.a, ev.data.b); break;
|
||||
case 'convert': text = mod.engine_convert(JSON.stringify(ev.data.request)); break;
|
||||
case 'variants': text = mod.engine_variants(ev.data.qasm); break;
|
||||
case 'shortcuts': text = mod.engine_shortcuts(ev.data.qasm, !!ev.data.thorough); break;
|
||||
case 'compile': text = e().compile(JSON.stringify(ev.data.request)); break;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
// - "Your hardware" says, in a browser tab, that such a run goes through the desktop
|
||||
// app or the command line, since a tab must not hold a provider's credential;
|
||||
// - an error in the program is marked on its line;
|
||||
// - a QIR module and a jeff module open as OpenQASM 3 through the engine, with its
|
||||
// notes and check, and a module its profile forbids is refused with its code;
|
||||
// - a rotation runs on the state vector, ⟨Z0⟩ = cos 0.3;
|
||||
// - a device target: its coupling map with each pair and qubit coloured by its error,
|
||||
// a run placed on it and simulated under its noise with the target's hash in the
|
||||
|
|
@ -212,6 +214,25 @@ await page.keyboard.press('ControlOrMeta+End');
|
|||
for (let i = 0; i < 10; i++) await page.keyboard.press('Backspace');
|
||||
await page.waitForFunction(() => /qubits/.test(document.querySelector('#qs-lint')?.textContent ?? ''), null, { timeout: LONG });
|
||||
|
||||
// A program in another format: QIR and jeff opened, read by the engine to
|
||||
// OpenQASM 3 with its notes and its check; a module the reader refuses keeps
|
||||
// the editor as it was and says why, with its code.
|
||||
{
|
||||
const formats = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', 'quantum-conformance', 'formats');
|
||||
await page.setInputFiles('#qs-open-file', { name: 'bell.ll', mimeType: 'text/plain', buffer: readFileSync(join(formats, 'qir', 'bell_base.ll')) });
|
||||
await page.waitForFunction(() => /read from QIR/.test(document.querySelector('#qs-shows')?.textContent ?? ''), null, { timeout: LONG });
|
||||
const fromQir = await page.evaluate(() => window.quantumStudio.view.state.doc.toString());
|
||||
check(/^\/\/ Read from QIR 2\.0, base profile/m.test(fromQir) && /OPENQASM 3\.0;/.test(fromQir) && /cx q\[0\], q\[1\];/.test(fromQir) && /checked: equivalent/.test(await page.textContent('#qs-shows')), `a QIR module opens as OpenQASM 3, checked (${(await page.textContent('#qs-shows')).slice(0, 120)}…)`);
|
||||
await page.setInputFiles('#qs-open-file', { name: 'ghz.jeff', mimeType: 'application/octet-stream', buffer: readFileSync(join(formats, 'jeff', 'upstream', 'ghz-linear_3.jeff')) });
|
||||
await page.waitForFunction(() => /read from jeff/.test(document.querySelector('#qs-shows')?.textContent ?? ''), null, { timeout: LONG });
|
||||
const fromJeff = await page.evaluate(() => window.quantumStudio.view.state.doc.toString());
|
||||
check(/Read from jeff 0\.3/.test(fromJeff) && /qubit\[3\] q;/.test(fromJeff) && /\[Q715\]/.test(await page.textContent('#qs-shows')), `a jeff module opens as OpenQASM 3 with the reader's notes (${(await page.textContent('#qs-shows')).slice(0, 160)}…)`);
|
||||
await page.waitForFunction(() => /qubits/.test(document.querySelector('#qs-lint')?.textContent ?? ''), null, { timeout: LONG });
|
||||
await page.setInputFiles('#qs-open-file', { name: 'forbidden.ll', mimeType: 'text/plain', buffer: readFileSync(join(formats, 'qir', 'refuse', 'base_branch.ll')) });
|
||||
await page.waitForFunction(() => /does not read as QIR/.test(document.querySelector('.qs-status')?.textContent ?? ''), null, { timeout: LONG });
|
||||
check(/\[Q704\]/.test(await page.textContent('.qs-status')) && (await page.evaluate(() => window.quantumStudio.view.state.doc.toString())) === fromJeff, `a module its profile forbids is refused with its code, the editor kept (${await page.textContent('.qs-status')})`);
|
||||
}
|
||||
|
||||
// A rotation: any angle, on the state vector.
|
||||
await page.selectOption('#qs-example', 'rotation');
|
||||
await page.waitForFunction(() => /State vector/.test(document.querySelector('#qs-plan')?.textContent ?? ''), null, { timeout: LONG });
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"schema": "wai.quantum.docs-manifest/1",
|
||||
"about": "The documents check_docs.py runs: the WAI Quantum READMEs and docs pages (engine, command line, service, Python, Studio, desktop, editors, providers, the compiler, estimates, verdicts, error correction, the feature matrix and the version policy; the service's self-hosting, scheduler and provenance pages; the views' engine), the agent skill, the course's lessons, and their translations.",
|
||||
"about": "The documents check_docs.py runs: the WAI Quantum READMEs and docs pages (engine, command line, service, Python, Studio, desktop, editors, providers, the compiler, estimates, verdicts, error correction, other formats, the feature matrix and the version policy; the service's self-hosting, scheduler and provenance pages; the views' engine), the agent skill, the course's lessons, and their translations.",
|
||||
"docs": [
|
||||
"wai/wai-quantum/README.md",
|
||||
"wai/wai-quantum/README.zh-CN.md",
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
"wai/wai-quantum/docs/estimate.md",
|
||||
"wai/wai-quantum/docs/verdicts.md",
|
||||
"wai/wai-quantum/docs/job-refusals.md",
|
||||
"wai/wai-quantum/docs/formats.md",
|
||||
"wai/wai-quantum/docs/qasm-diagnostics.md",
|
||||
"wai/wai-quantum/docs/qasm-feature-matrix.md",
|
||||
"wai/wai-quantum/docs/qec.md",
|
||||
|
|
|
|||
|
|
@ -222,6 +222,18 @@ The critique's figures are computed, not estimated: gates by kind, two-qubit gat
|
|||
|
||||
A cheap route proves a design classically easy. None being cheap proves nothing about hardness: other methods, approximate ones above all, may cost far less.
|
||||
|
||||
## Other formats
|
||||
|
||||
```sh runnable
|
||||
wai-quantum convert prog.qasm --to qir > prog.ll # QIR 2.0, the base profile (adaptive for a program that branches)
|
||||
wai-quantum convert prog.ll --to jeff -o prog.jeff # jeff; the format read is found from the file
|
||||
wai-quantum convert prog.jeff --to qasm # back to OpenQASM 3
|
||||
wai-quantum run prog.ll --shots 100 # every verb reads QIR (.ll, .qir) and jeff (.jeff)
|
||||
wai-quantum equivalent prog.jeff prog.qasm # exit 0: the same circuit
|
||||
```
|
||||
|
||||
`convert` carries a program between OpenQASM 3, QIR (LLVM text) and jeff, and checks every conversion: what it writes is read back and held to the program by the equivalence check, and `check:` on standard error says how (`--no-check` skips it; `--json` gives everything as data, jeff as base64). QIR is read under the profile its entry point names, base or adaptive, and what the profile forbids is refused with its line; `--profile` chooses the profile QIR is written under. A rotation at any angle is read at its exact double, and a note says the bit-exact method refuses it. Every other verb reads QIR and jeff by the file's extension, or by `--from qir` or `--from jeff`, the reader's notes on standard error. A construct a reader cannot hold exactly is refused with a code from `Q700` and its place; `wai-quantum diagnostics` lists them, and [the formats page](../wai-quantum/docs/formats.md) says what each reader takes.
|
||||
|
||||
## Your own hardware
|
||||
|
||||
Bring your own quantum: your device, your account with a provider, or a simulator you trust, listed in your registry with its credential in the operating system's keychain ([the guide](../wai-quantum-qpu/bring-your-own-quantum.md), [the protocol](../extensions/quantum-providers.md)).
|
||||
|
|
@ -348,12 +360,13 @@ wai-quantum verify sweep.json # the set's receipt, each item's, the r
|
|||
|
||||
`wai-quantum mcp` is a Model Context Protocol server on standard input and output. Its tools are:
|
||||
|
||||
- `run_quantum_circuit` (with `intent` and `repair`; its verdict in every answer)
|
||||
- `run_quantum_circuit` (with `intent` and `repair`; its verdict in every answer; its program as `qasm`, or in another format as `source`, as the job service takes it)
|
||||
- `plan_quantum_circuit`
|
||||
- `lint_qasm`
|
||||
- `repair_qasm` (verdicts and repairs, above)
|
||||
- `critique_qasm`
|
||||
- `check_equivalent`
|
||||
- `convert_program`
|
||||
- `improve_qasm`
|
||||
- `classical_shortcuts`
|
||||
- `compile_qasm` (compiling, above)
|
||||
|
|
|
|||
|
|
@ -220,6 +220,18 @@ wai-quantum shortcuts prog.qasm # 模拟它的每一条精确经典
|
|||
|
||||
存在一条便宜的途径,就证明该设计在经典上是容易的。没有一条途径便宜,并不能证明任何关于其困难性的结论:其他方法,尤其是近似方法,代价可能低得多。
|
||||
|
||||
## 其他格式
|
||||
|
||||
```sh runnable
|
||||
wai-quantum convert prog.qasm --to qir > prog.ll # QIR 2.0,基础配置文件(分支的程序则用自适应配置文件)
|
||||
wai-quantum convert prog.ll --to jeff -o prog.jeff # jeff;所读格式由文件判断
|
||||
wai-quantum convert prog.jeff --to qasm # 转回 OpenQASM 3
|
||||
wai-quantum run prog.ll --shots 100 # 每个命令都能读取 QIR(.ll、.qir)和 jeff(.jeff)
|
||||
wai-quantum equivalent prog.jeff prog.qasm # 退出状态 0:同一条线路
|
||||
```
|
||||
|
||||
`convert` 在 OpenQASM 3、QIR(LLVM 文本)和 jeff 之间转换程序,并检查每一次转换:写出的结果会被读回,并由等价检查与原程序比对,标准错误上的 `check:` 说明是如何判定的(`--no-check` 跳过检查;`--json` 以数据形式给出全部内容,jeff 以 base64 给出)。QIR 按其入口点所声明的配置文件(base 或 adaptive)读取,配置文件禁止的内容按行拒绝;`--profile` 选择写出 QIR 时所用的配置文件。任意角度的旋转按其精确的双精度值读取,并附注说明逐位精确的方法不接受它。其他每个命令都按文件扩展名读取 QIR 和 jeff,或按 `--from qir`、`--from jeff` 读取,读取器的说明输出到标准错误。读取器无法精确表示的构造会以 `Q700` 起的代码及其位置拒绝;`wai-quantum diagnostics` 列出这些代码,[格式说明页](../wai-quantum/docs/formats.md)说明每个读取器接受什么。
|
||||
|
||||
## 你自己的硬件
|
||||
|
||||
自带你的量子资源:你的设备、你在某个提供方处的账户,或你信任的模拟器,登记在你的注册表中,其凭据存放在操作系统的钥匙串里([指南](../wai-quantum-qpu/bring-your-own-quantum.md)、[协议](../extensions/quantum-providers.md))。
|
||||
|
|
@ -346,12 +358,13 @@ wai-quantum verify sweep.json # 程序集的回执、每一项的回
|
|||
|
||||
`wai-quantum mcp` 是一个基于标准输入输出的 Model Context Protocol(MCP)服务器。它的工具有:
|
||||
|
||||
- `run_quantum_circuit`(带 `intent` 和 `repair`;每个回答中都有其判定)
|
||||
- `run_quantum_circuit`(带 `intent` 和 `repair`;每个回答中都有其判定;程序以 `qasm` 给出,或以其他格式作为 `source` 给出,与作业服务的接受方式相同)
|
||||
- `plan_quantum_circuit`
|
||||
- `lint_qasm`
|
||||
- `repair_qasm`(判定与修复,见上文)
|
||||
- `critique_qasm`
|
||||
- `check_equivalent`
|
||||
- `convert_program`
|
||||
- `improve_qasm`
|
||||
- `classical_shortcuts`
|
||||
- `compile_qasm`(编译,见上文)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -47,6 +47,7 @@ Runs on this machine, signed with the user's key; nothing leaves the machine.
|
|||
- `repair_qasm`: Repair a program on its flagged lines
|
||||
- `critique_qasm`: Critique an OpenQASM program
|
||||
- `check_equivalent`: Check two programs are the same circuit
|
||||
- `convert_program`: Convert a program between formats
|
||||
- `improve_qasm`: Improve an OpenQASM program
|
||||
- `classical_shortcuts`: Find a program's classical shortcuts
|
||||
- `compile_qasm`: Compile a program, every pass checked
|
||||
|
|
@ -95,6 +96,7 @@ Runs on this machine, signed with the user's key; nothing leaves the machine.
|
|||
- `verify_quantum_receipt`: Verify a result's receipt
|
||||
- `critique_qasm`: Critique a quantum program
|
||||
- `check_equivalent`: Check two quantum programs are the same circuit
|
||||
- `convert_program`: Convert a program between formats
|
||||
- `improve_qasm`: Improve a quantum program
|
||||
- `classical_shortcuts`: Find a quantum program's classical shortcuts
|
||||
- `compile_qasm`: Compile a quantum program, every pass checked
|
||||
|
|
|
|||
|
|
@ -7,10 +7,45 @@
|
|||
"description": "Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"qasm"
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"qasm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
],
|
||||
"description": "Its format."
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text: QIR (LLVM text) or OpenQASM."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64: jeff."
|
||||
}
|
||||
}
|
||||
},
|
||||
"qasm": {
|
||||
"type": "string",
|
||||
"description": "The program, OpenQASM 3 or 2: registers and broadcast over them, the standard gates, ctrl/negctrl modifiers, gate definitions, measurement and reset anywhere, if on measured bits, and generators (integer input, const and for loops, one program for a family of circuits; give the inputs' values in \"inputs\"). while, inv and pow are refused with their line."
|
||||
|
|
@ -542,6 +577,11 @@
|
|||
"required": [
|
||||
"programs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
|
@ -549,6 +589,30 @@
|
|||
"type": "string",
|
||||
"description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use."
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64 (jeff)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"shots": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
@ -3368,6 +3432,11 @@
|
|||
"required": [
|
||||
"programs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
|
@ -3375,6 +3444,30 @@
|
|||
"type": "string",
|
||||
"description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use."
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64 (jeff)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"shots": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
@ -6795,10 +6888,45 @@
|
|||
"description": "The method a program would run on and why, the memory and work it would take, without running it.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"qasm"
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"qasm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
],
|
||||
"description": "Its format."
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text: QIR (LLVM text) or OpenQASM."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64: jeff."
|
||||
}
|
||||
}
|
||||
},
|
||||
"qasm": {
|
||||
"type": "string",
|
||||
"description": "The program, OpenQASM 3 or 2: registers and broadcast over them, the standard gates, ctrl/negctrl modifiers, gate definitions, measurement and reset anywhere, if on measured bits, and generators (integer input, const and for loops, one program for a family of circuits; give the inputs' values in \"inputs\"). while, inv and pow are refused with their line."
|
||||
|
|
@ -12570,6 +12698,274 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "convert_program",
|
||||
"title": "Convert a program between formats",
|
||||
"description": "Carry a program between OpenQASM 3, QIR (LLVM text, read under its base and adaptive profiles, written as QIR 2.0) and jeff (its Cap'n Proto message, as base64). The answer is the program written, the program as OpenQASM 3 (what every other tool takes), each note with its code (a rotation at an arbitrary angle, a custom gate read by its name, what a format leaves out), what was read and written, and the check: the output read back and held to the program by the equivalence ladder. A construct a reader cannot hold exactly is refused with its code (Q700 to Q721) and its place: quote the code, and never guess around it.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"to"
|
||||
],
|
||||
"properties": {
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text: OpenQASM or QIR."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64: jeff."
|
||||
},
|
||||
"from": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
],
|
||||
"description": "Its format; found from its bytes when not given."
|
||||
},
|
||||
"to": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
],
|
||||
"description": "The format to write."
|
||||
},
|
||||
"profile": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"base",
|
||||
"adaptive"
|
||||
],
|
||||
"description": "QIR's profile to write: by default base when the program's measurements all come at the end, else adaptive."
|
||||
},
|
||||
"check": {
|
||||
"type": "boolean",
|
||||
"description": "false: write it without the check."
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputSchema": {
|
||||
"$id": "wai-quantum://schemas/convert_program/1",
|
||||
"type": "object",
|
||||
"description": "A program carried from one format to another (OpenQASM 3, QIR as LLVM text, jeff as its Cap'n Proto message) and checked (engine::formats::convert_json): the program written, the program as read in OpenQASM 3, the readers' and writer's notes with their codes, what was read and written, and the check that holds the output to the input.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"description": "A program carried from one format to another (OpenQASM 3, QIR as LLVM text, jeff as its Cap'n Proto message) and checked (engine::formats::convert_json): the program written, the program as read in OpenQASM 3, the readers' and writer's notes with their codes, what was read and written, and the check that holds the output to the input.",
|
||||
"required": [
|
||||
"ok",
|
||||
"format",
|
||||
"from",
|
||||
"to",
|
||||
"qasm",
|
||||
"notes",
|
||||
"read",
|
||||
"written",
|
||||
"check"
|
||||
],
|
||||
"properties": {
|
||||
"ok": {
|
||||
"const": true
|
||||
},
|
||||
"format": {
|
||||
"const": "wai.quantum.convert/1"
|
||||
},
|
||||
"from": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"to": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program written, for a text format (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program written, for a binary format (jeff), as standard base64."
|
||||
},
|
||||
"qasm": {
|
||||
"type": "string",
|
||||
"description": "The program as read, as OpenQASM 3: what every other tool takes."
|
||||
},
|
||||
"notes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"description": "One of the reader's diagnostics: its code, what happens to the construct it is about, its message (without the line or the code), and where it stands.",
|
||||
"required": [
|
||||
"code",
|
||||
"outcome",
|
||||
"message"
|
||||
],
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"outcome": {
|
||||
"enum": [
|
||||
"refused",
|
||||
"lowered",
|
||||
"carried",
|
||||
"preserved",
|
||||
"warned"
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"line": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"column": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"length": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Each warning and note, with its code (Q7xx for the formats) and, for QIR, its line."
|
||||
},
|
||||
"read": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "What was read: the format, its version, a QIR module's profile, entry point, qubits, results and declared capabilities, a jeff module's tool, entry point, qubits and bits."
|
||||
},
|
||||
"written": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "What was written: the format, its version, and QIR's profile."
|
||||
},
|
||||
"check": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"what",
|
||||
"verdict"
|
||||
],
|
||||
"properties": {
|
||||
"what": {
|
||||
"type": "string",
|
||||
"description": "What was held to what."
|
||||
},
|
||||
"verdict": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"verdict",
|
||||
"how",
|
||||
"why"
|
||||
],
|
||||
"properties": {
|
||||
"verdict": {
|
||||
"enum": [
|
||||
"equivalent",
|
||||
"different",
|
||||
"unchecked"
|
||||
]
|
||||
},
|
||||
"how": {
|
||||
"enum": [
|
||||
"tableau",
|
||||
"exact",
|
||||
"rewrites",
|
||||
"random",
|
||||
"state",
|
||||
"shape",
|
||||
"steps",
|
||||
"distribution",
|
||||
"identity",
|
||||
"none"
|
||||
],
|
||||
"description": "The equivalence ladder's check (tableau, exact and rewrites are proofs; random is evidence); steps: the same steps one for one; distribution: every outcome's probability the same (evidence); identity: OpenQASM passed through; none: unchecked."
|
||||
},
|
||||
"why": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_phase": {
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "The output read back and held to the program read (or, for a program read into OpenQASM, written back to its format and read again), or null when no check was asked."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "A refusal as data: the message, every code in it (the last is the code), its outcome and meaning as the code's table gives them. A host that refuses for its own reasons gives the error alone.",
|
||||
"required": [
|
||||
"error"
|
||||
],
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"codes": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"outcome": {
|
||||
"enum": [
|
||||
"refused",
|
||||
"retry",
|
||||
"failed",
|
||||
"lowered",
|
||||
"carried",
|
||||
"preserved",
|
||||
"warned",
|
||||
"dropped",
|
||||
"defaulted"
|
||||
]
|
||||
},
|
||||
"meaning": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "improve_qasm",
|
||||
"title": "Improve an OpenQASM program",
|
||||
|
|
@ -26758,11 +27154,45 @@
|
|||
"description": "Run an OpenQASM program here as it would run on a device target: compiled exactly to the target's native gates, placed on the qubits and routes most likely to succeed (the expected success given beside the fewest-swaps layout's), checked against the circuit, and simulated under the noise its calibration gives (each gate's error, T1, T2 and durations, idling, and each qubit's readout), on the density matrix or by trajectories. Counts and expectation values, their distance from the ideal distribution, the noise derived, and a receipt signed with this user's key that binds the target's hash. A model of the device, not a run on it: quote it as such. Every angle must be a dyadic multiple of 2π.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"qasm",
|
||||
"target"
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"qasm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
],
|
||||
"description": "Its format."
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text: QIR (LLVM text) or OpenQASM."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64: jeff."
|
||||
}
|
||||
}
|
||||
},
|
||||
"qasm": {
|
||||
"type": "string",
|
||||
"description": "The program, OpenQASM 3 or 2: registers and broadcast over them, the standard gates, ctrl/negctrl modifiers, gate definitions, measurement and reset anywhere, if on measured bits, and generators (integer input, const and for loops, one program for a family of circuits; give the inputs' values in \"inputs\"). while, inv and pow are refused with their line."
|
||||
|
|
@ -27224,7 +27654,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"target"
|
||||
]
|
||||
},
|
||||
"outputSchema": {
|
||||
"$id": "wai-quantum://schemas/run_on_target/1",
|
||||
|
|
@ -27294,6 +27727,11 @@
|
|||
"required": [
|
||||
"programs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
|
@ -27301,6 +27739,30 @@
|
|||
"type": "string",
|
||||
"description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use."
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64 (jeff)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"shots": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
@ -30120,6 +30582,11 @@
|
|||
"required": [
|
||||
"programs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
|
@ -30127,6 +30594,30 @@
|
|||
"type": "string",
|
||||
"description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use."
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64 (jeff)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"shots": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
@ -36482,6 +36973,11 @@
|
|||
"required": [
|
||||
"programs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
|
@ -36489,6 +36985,30 @@
|
|||
"type": "string",
|
||||
"description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use."
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64 (jeff)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"shots": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
@ -39308,6 +39828,11 @@
|
|||
"required": [
|
||||
"programs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"source"
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
|
@ -39315,6 +39840,30 @@
|
|||
"type": "string",
|
||||
"description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use."
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"format"
|
||||
],
|
||||
"description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.",
|
||||
"properties": {
|
||||
"format": {
|
||||
"enum": [
|
||||
"qasm",
|
||||
"qir",
|
||||
"jeff"
|
||||
]
|
||||
},
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "The program's text (OpenQASM, QIR)."
|
||||
},
|
||||
"program_base64": {
|
||||
"type": "string",
|
||||
"description": "The program's bytes as base64 (jeff)."
|
||||
}
|
||||
}
|
||||
},
|
||||
"shots": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -37,6 +37,7 @@
|
|||
"run": { "source": "Run a program here, planned as the job service plans it, and sign the result", "text": "在本机运行程序,按作业服务的方式规划,并为结果签名" },
|
||||
"plan": { "source": "Show the method a program would run on and why, without running it", "text": "显示程序将在哪种方法上运行及其原因,而不运行它" },
|
||||
"instance": { "source": "Write a generator out at its `--input` values, as plain OpenQASM", "text": "按 `--input` 给出的取值,把生成器写成普通的 OpenQASM" },
|
||||
"convert": { "source": "Carry a program between formats (OpenQASM 3, QIR as LLVM text, jeff), every conversion checked: what is written is read back and held to the program by the equivalence ladder; notes and the check go to standard error (exit 1 refused, 2 the check found it different)", "text": "在格式之间转换程序(OpenQASM 3、以 LLVM 文本表示的 QIR、jeff),每次转换都经过检查:写出的结果会被读回,并由等价判定阶梯与原程序比对;说明和检查结果输出到标准错误(退出状态 1 表示被拒绝,2 表示检查发现两者不同)" },
|
||||
"lint": { "source": "Check a program and print each problem with its line", "text": "检查程序,并打印每个问题及其所在的行" },
|
||||
"draw": { "source": "Draw a program's circuit: as text, or as an SVG image, LaTeX (plain TikZ) or words", "text": "绘制程序的线路:以文本、SVG 图像、LaTeX(纯 TikZ)或文字描述的形式" },
|
||||
"debug": { "source": "Step through a program on the engine's exact methods and look into the state at a position or before a line, or list every branch at its measurements in the middle with its weight", "text": "在引擎的精确方法上单步执行程序,查看某个位置或某一行之前的状态,或列出中途测量处的每个分支及其权重" },
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ Generated by `wai-quantum docs skill` from the servers' own lists; `wai-quantum
|
|||
- `repair_qasm`: Repair a program on its flagged lines
|
||||
- `critique_qasm`: Critique an OpenQASM program
|
||||
- `check_equivalent`: Check two programs are the same circuit
|
||||
- `convert_program`: Convert a program between formats
|
||||
- `improve_qasm`: Improve an OpenQASM program
|
||||
- `classical_shortcuts`: Find a program's classical shortcuts
|
||||
- `compile_qasm`: Compile a program, every pass checked
|
||||
|
|
@ -57,6 +58,7 @@ Generated by `wai-quantum docs skill` from the servers' own lists; `wai-quantum
|
|||
- `verify_quantum_receipt`: Verify a result's receipt
|
||||
- `critique_qasm`: Critique a quantum program
|
||||
- `check_equivalent`: Check two quantum programs are the same circuit
|
||||
- `convert_program`: Convert a program between formats
|
||||
- `improve_qasm`: Improve a quantum program
|
||||
- `classical_shortcuts`: Find a quantum program's classical shortcuts
|
||||
- `compile_qasm`: Compile a quantum program, every pass checked
|
||||
|
|
|
|||
|
|
@ -126,6 +126,22 @@ if "$W" equivalent "$tmp/twice.qasm" "$tmp/ghz.qasm" > "$tmp/differ"; then fail
|
|||
has "$tmp/differ" "^different: one has 2 qubits and the other 3"
|
||||
echo "critique, improve, equivalent: ok"
|
||||
|
||||
# Other formats: OpenQASM written as QIR and jeff, each read back and checked,
|
||||
# every verb reading them, and a module its profile forbids refused on its line.
|
||||
"$W" convert "$tmp/twice.qasm" --to qir > "$tmp/twice.ll" 2> "$tmp/convert"
|
||||
has "$tmp/convert" "^check: equivalent (tableau)"
|
||||
has "$tmp/twice.ll" '"qir_profiles"="base_profile"'
|
||||
"$W" convert "$tmp/twice.ll" --to jeff -o "$tmp/twice.jeff" 2> "$tmp/convert"
|
||||
has "$tmp/convert" "^check: equivalent (tableau)"
|
||||
"$W" equivalent "$tmp/twice.jeff" "$tmp/twice.qasm" > "$tmp/same" 2>/dev/null
|
||||
has "$tmp/same" "^equivalent"
|
||||
"$W" run "$tmp/twice.ll" --shots 64 --json > "$tmp/fromqir.json"
|
||||
"$W" verify "$tmp/fromqir.json" > /dev/null || fail "a run of a QIR module did not verify"
|
||||
printf 'define i64 @main() #0 {\nentry:\n call void @__quantum__qis__mz__body(ptr null, ptr writeonly null)\n call void @__quantum__qis__x__body(ptr null)\n ret i64 0\n}\nattributes #0 = { "entry_point" "qir_profiles"="base_profile" "required_num_qubits"="1" "required_num_results"="1" }\n' > "$tmp/forbidden.ll"
|
||||
if "$W" convert "$tmp/forbidden.ll" --to qasm > /dev/null 2> "$tmp/refused"; then fail "a gate after a measurement under the base profile was read"; fi
|
||||
has "$tmp/refused" "line 4: the base profile forbids a gate on qubit 0 after its measurement \\[Q704\\]"
|
||||
echo "convert: QIR and jeff, written, read back and checked; a profile's refusal on its line: ok"
|
||||
|
||||
"$W" shortcuts "$tmp/ghz.qasm" > "$tmp/shortcuts"
|
||||
has "$tmp/shortcuts" "^Classically easy at any width"
|
||||
printf 'OPENQASM 3.0;\nqubit[8] q;\nh q;\ncz q[0], q[1];\ncz q[1], q[2];\ncz q[2], q[3];\ncz q[3], q[4];\ncz q[4], q[5];\ncz q[5], q[6];\ncz q[6], q[7];\ncz q[7], q[0];\nrz(0.3) q;\n' > "$tmp/ring.qasm"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
//! wai-quantum repair prog.qasm > fixed.qasm # the mechanical fixes, on the lines the diagnostics flag alone
|
||||
//! wai-quantum run ghz.qasm --input n=40 # a generator, read at n = 40
|
||||
//! wai-quantum instance qft.qasm --input n=5 # a generator written out as plain OpenQASM
|
||||
//! wai-quantum convert prog.qasm --to qir # QIR 2.0 (or jeff, or OpenQASM 3), the conversion checked
|
||||
//! wai-quantum run prog.ll --shots 1000 # every verb reads QIR (.ll) and jeff (.jeff); --from names one
|
||||
//! wai-quantum discover new ghz.json # the workbench: an archive for a specification
|
||||
//! wai-quantum discover search ghz.json # cheaper generators, each checked at every size
|
||||
//! wai-quantum history blame prog.qasm # whose hand each line and gate is in
|
||||
|
|
@ -129,6 +131,9 @@ struct Cli {
|
|||
/// The language of the words the command line writes itself, en or zh-CN (by default the one LANG names); results, codes and the engine's own messages stay in English
|
||||
#[arg(long, global = true, value_name = "LOCALE")]
|
||||
lang: Option<String>,
|
||||
/// The format of every program the command reads: qasm, qir (LLVM text) or jeff; by default the file's extension says (.ll or .qir is QIR, .jeff is jeff), and OpenQASM otherwise
|
||||
#[arg(long, global = true, value_name = "FORMAT", value_parser = format_arg)]
|
||||
from: Option<wai_quantum::engine::formats::Format>,
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
|
@ -160,6 +165,26 @@ enum Command {
|
|||
/// The program; `-` or nothing reads standard input
|
||||
file: Option<PathBuf>,
|
||||
},
|
||||
/// Carry a program between formats (OpenQASM 3, QIR as LLVM text, jeff), every conversion checked: what is written is read back and held to the program by the equivalence ladder; notes and the check go to standard error (exit 1 refused, 2 the check found it different)
|
||||
Convert {
|
||||
/// The program; `-` or nothing reads standard input; its format is --from, else its extension, else what its bytes look like
|
||||
file: Option<PathBuf>,
|
||||
/// The format to write: qasm, qir or jeff
|
||||
#[arg(long, value_name = "FORMAT", value_parser = format_arg)]
|
||||
to: wai_quantum::engine::formats::Format,
|
||||
/// QIR's profile, base or adaptive: by default the base profile when the program's measurements all come at the end, else the adaptive one
|
||||
#[arg(long)]
|
||||
profile: Option<String>,
|
||||
/// Write the program to this file (jeff is binary: give a file, or --json for its base64)
|
||||
#[arg(short = 'o', long, value_name = "FILE")]
|
||||
output: Option<PathBuf>,
|
||||
/// Print the conversion as JSON: the program (base64 for jeff), the program as OpenQASM, the notes, what was read and written, and the check
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
/// Write it without the check
|
||||
#[arg(long)]
|
||||
no_check: bool,
|
||||
},
|
||||
/// Check a program and print each problem with its line
|
||||
Lint {
|
||||
/// The program; `-` or nothing reads standard input
|
||||
|
|
@ -559,7 +584,52 @@ fn die(msg: &str) -> ! {
|
|||
/// (a program with integer `input`s) is written out at the `--input` values,
|
||||
/// so every command reads one circuit of its family.
|
||||
fn read_input(file: Option<&Path>) -> Result<String, String> {
|
||||
at_inputs(read_text(file)?, &INPUTS.get().cloned().unwrap_or_default())
|
||||
at_inputs(read_program(file)?, &INPUTS.get().cloned().unwrap_or_default())
|
||||
}
|
||||
|
||||
/// The format `--from` gives, for every program read.
|
||||
static FROM: std::sync::OnceLock<Option<wai_quantum::engine::formats::Format>> = std::sync::OnceLock::new();
|
||||
|
||||
fn format_arg(s: &str) -> Result<wai_quantum::engine::formats::Format, String> {
|
||||
wai_quantum::engine::formats::Format::parse(s).ok_or_else(|| format!("{s}: the formats are qasm, qir and jeff"))
|
||||
}
|
||||
|
||||
/// The bytes of `file`, or standard input for `-` or none.
|
||||
fn read_bytes(file: Option<&Path>) -> Result<Vec<u8>, String> {
|
||||
match file {
|
||||
Some(p) if p != Path::new("-") => std::fs::read(p).map_err(|e| format!("{}: {e}", p.display())),
|
||||
_ => {
|
||||
use std::io::Read as _;
|
||||
let mut b = Vec::new();
|
||||
std::io::stdin().read_to_end(&mut b).map_err(|e| format!("standard input: {e}"))?;
|
||||
Ok(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The format a program is in: `--from`, else its file's extension (`.ll`
|
||||
/// and `.qir` are QIR, `.jeff` is jeff), else OpenQASM.
|
||||
fn format_of(file: Option<&Path>) -> wai_quantum::engine::formats::Format {
|
||||
use wai_quantum::engine::formats::Format;
|
||||
if let Some(Some(f)) = FROM.get() {
|
||||
return *f;
|
||||
}
|
||||
file.and_then(|p| Format::from_extension(&p.to_string_lossy())).unwrap_or(Format::Qasm)
|
||||
}
|
||||
|
||||
/// The program in `file` as OpenQASM: one in another format is read to it,
|
||||
/// its notes on standard error.
|
||||
fn read_program(file: Option<&Path>) -> Result<String, String> {
|
||||
use wai_quantum::engine::formats::{self, Format};
|
||||
let f = format_of(file);
|
||||
if f == Format::Qasm {
|
||||
return read_text(file);
|
||||
}
|
||||
let r = formats::read(f, &read_bytes(file)?).map_err(|d| d.to_string())?;
|
||||
for n in &r.notes {
|
||||
eprintln!("wai-quantum: {}: {n}", f.name());
|
||||
}
|
||||
Ok(r.qasm)
|
||||
}
|
||||
|
||||
/// `text` as one circuit: a generator written out at `inputs`, any other
|
||||
|
|
@ -588,7 +658,7 @@ fn read_text(file: Option<&Path>) -> Result<String, String> {
|
|||
/// request carries the history's account of the version the file holds;
|
||||
/// with `--intent`, what the program must do.
|
||||
fn job_request(job: &Job) -> Result<Value, String> {
|
||||
let text = read_text(job.file.as_deref())?;
|
||||
let text = read_program(job.file.as_deref())?;
|
||||
let inputs = INPUTS.get().cloned().unwrap_or_default();
|
||||
// A sweep sends the program with its inputs, which the sweep gives values.
|
||||
if !job.sweep.is_empty() && !inputs.is_empty() {
|
||||
|
|
@ -599,7 +669,7 @@ fn job_request(job: &Job) -> Result<Value, String> {
|
|||
if !job.programs.is_empty() {
|
||||
let mut all = vec![req["qasm"].take()];
|
||||
for p in &job.programs {
|
||||
all.push(json!(at_inputs(read_text(Some(p))?, &inputs)?));
|
||||
all.push(json!(at_inputs(read_program(Some(p))?, &inputs)?));
|
||||
}
|
||||
req.as_object_mut().map(|o| o.remove("qasm"));
|
||||
req["programs"] = Value::Array(all);
|
||||
|
|
@ -940,6 +1010,54 @@ fn print_dry_run(p: &Value) {
|
|||
println!("you {} active, {} submissions left in this window", p["client"]["active_jobs"], p["client"]["submissions_left"]);
|
||||
}
|
||||
|
||||
/// `convert`: the program in `file` written as `to`, to `output` or standard
|
||||
/// output, its notes and the check on standard error (or all of it as JSON).
|
||||
fn convert(file: Option<&Path>, to: wai_quantum::engine::formats::Format, profile: Option<&str>, output: Option<&Path>, as_json: bool, no_check: bool) {
|
||||
use std::io::{IsTerminal, Write as _};
|
||||
use wai_quantum::engine::formats::{self, Format, Profile};
|
||||
let bytes = read_bytes(file).unwrap_or_else(|e| die(&e));
|
||||
let from = match FROM.get() {
|
||||
Some(Some(f)) => *f,
|
||||
_ => file.and_then(|p| Format::from_extension(&p.to_string_lossy())).unwrap_or_else(|| Format::sniff(&bytes)),
|
||||
};
|
||||
let profile = profile.map(|p| Profile::parse(p).unwrap_or_else(|| die(&format!("{p}: the QIR profiles are base and adaptive"))));
|
||||
let c = formats::convert(from, to, &bytes, profile, !no_check).unwrap_or_else(|d| die(&d.to_string()));
|
||||
let verdict = c.check["verdict"]["verdict"].as_str().unwrap_or("");
|
||||
if as_json {
|
||||
let mut v = json!({
|
||||
"ok": true, "format": formats::FORMAT, "from": from.name(), "to": to.name(), "qasm": c.qasm,
|
||||
"notes": c.notes.iter().map(|d| d.to_json()).collect::<Vec<_>>(), "read": c.read, "written": c.written, "check": c.check,
|
||||
});
|
||||
if to.is_binary() {
|
||||
v["program_base64"] = json!(formats::encode_base64(&c.output));
|
||||
} else {
|
||||
v["program"] = json!(String::from_utf8_lossy(&c.output));
|
||||
}
|
||||
if let Some(o) = output {
|
||||
std::fs::write(o, &c.output).unwrap_or_else(|e| die(&format!("{}: {e}", o.display())));
|
||||
}
|
||||
println!("{v}");
|
||||
} else {
|
||||
for n in &c.notes {
|
||||
eprintln!("note: {n}");
|
||||
}
|
||||
if !c.check.is_null() {
|
||||
eprintln!("check: {} ({}): {}", verdict, c.check["verdict"]["how"].as_str().unwrap_or(""), c.check["what"].as_str().unwrap_or(""));
|
||||
}
|
||||
match output {
|
||||
Some(o) => std::fs::write(o, &c.output).unwrap_or_else(|e| die(&format!("{}: {e}", o.display()))),
|
||||
None if to.is_binary() && std::io::stdout().is_terminal() => die("jeff is binary: give -o FILE, or --json for its base64"),
|
||||
None => {
|
||||
let mut out = std::io::stdout();
|
||||
out.write_all(&c.output).and_then(|_| out.flush()).unwrap_or_else(|e| die(&format!("standard output: {e}")));
|
||||
}
|
||||
}
|
||||
}
|
||||
if verdict == "different" {
|
||||
std::process::exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// The help a parse prints is in the person's language, so the language is read first.
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
|
@ -947,6 +1065,7 @@ fn main() {
|
|||
locale::set(loc);
|
||||
let cli = Cli::from_arg_matches(&locale::localize(Cli::command(), loc).get_matches_from(&args)).unwrap_or_else(|e| e.exit());
|
||||
let _ = INPUTS.set(cli.inputs.iter().cloned().collect());
|
||||
let _ = FROM.set(cli.from);
|
||||
match cli.command {
|
||||
#[cfg(feature = "providers")]
|
||||
Command::Run { job, out, key, provider } if provider.provider.is_some() => providers::run(&job, &out, &key, &provider),
|
||||
|
|
@ -1027,6 +1146,7 @@ fn main() {
|
|||
Command::Instance { file } => {
|
||||
print!("{}", read_input(file.as_deref()).unwrap_or_else(|e| die(&e)));
|
||||
}
|
||||
Command::Convert { file, to, profile, output, json, no_check } => convert(file.as_deref(), to, profile.as_deref(), output.as_deref(), json, no_check),
|
||||
Command::Lint { file, json } => {
|
||||
let name = file.as_deref().filter(|p| *p != Path::new("-")).map(|p| p.display().to_string()).unwrap_or_else(|| "<stdin>".into());
|
||||
let src = read_input(file.as_deref()).unwrap_or_else(|e| die(&e));
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ fn output_of(tool: &str) -> Option<&'static str> {
|
|||
"lint_qasm" => "tools.v1.json#/$defs/lint",
|
||||
"critique_qasm" => "tools.v1.json#/$defs/critique",
|
||||
"check_equivalent" => "tools.v1.json#/$defs/equivalence",
|
||||
"convert_program" => "tools.v1.json#/$defs/convert",
|
||||
"improve_qasm" => "tools.v1.json#/$defs/improve",
|
||||
"classical_shortcuts" => "tools.v1.json#/$defs/shortcuts",
|
||||
"draw_circuit" => "tools.v1.json#/$defs/draw",
|
||||
|
|
@ -99,8 +100,9 @@ fn output_of(tool: &str) -> Option<&'static str> {
|
|||
fn job_schema() -> Value {
|
||||
json!({
|
||||
"type": "object",
|
||||
"required": ["qasm"],
|
||||
"anyOf": wai_quantum::engine::formats::program_required(),
|
||||
"properties": {
|
||||
"source": wai_quantum::engine::formats::source_schema(),
|
||||
"qasm": { "type": "string", "description": "The program, OpenQASM 3 or 2: registers and broadcast over them, the standard gates, ctrl/negctrl modifiers, gate definitions, measurement and reset anywhere, if on measured bits, and generators (integer input, const and for loops, one program for a family of circuits; give the inputs' values in \"inputs\"). while, inv and pow are refused with their line." },
|
||||
"inputs": inputs_schema(),
|
||||
"shots": { "type": "integer", "minimum": 0, "description": "Shots to sample; 1024 when nothing else is asked." },
|
||||
|
|
@ -267,6 +269,7 @@ fn core_tools() -> Value {
|
|||
"description": "Whether two programs are the same circuit up to a global phase, and how the engine knows: equal tableaus for Clifford circuits at any size, every basis state to 8 qubits, checked rewrites of one followed by the other's inverse to nothing (a proof at any width), random product states to 22 qubits (evidence, not proof), or unchecked with the reason. Its `verdict` is that decision; `verification` is the level it reached, as every tool's verdict states it.",
|
||||
"inputSchema": { "type": "object", "required": ["a", "b"], "properties": { "a": { "type": "string", "description": "The first program." }, "b": { "type": "string", "description": "The second program." }, "inputs": inputs_schema() } },
|
||||
},
|
||||
wai_quantum::engine::formats::tool(),
|
||||
{
|
||||
"name": "improve_qasm",
|
||||
"title": "Improve an OpenQASM program",
|
||||
|
|
@ -471,10 +474,24 @@ fn call(name: &str, args: &Value, memory_gb: u64, key: &SigningKey, client: &Cli
|
|||
let result = wai_quantum::engine::pulse::call(op, args)?;
|
||||
return Ok(wai_quantum::engine::pulse::seal(args, result, key));
|
||||
}
|
||||
// A run's program may come in another format, read to its qasm first, as
|
||||
// the job service reads it.
|
||||
let expanded;
|
||||
let args = match name {
|
||||
"run_quantum_circuit" | "plan_quantum_circuit" | "run_on_target" => match wai_quantum::engine::formats::expand(args)? {
|
||||
Some(e) => {
|
||||
expanded = e;
|
||||
&expanded
|
||||
}
|
||||
None => args,
|
||||
},
|
||||
_ => args,
|
||||
};
|
||||
// A tool that reads a generator at its inputs itself takes them as given.
|
||||
let raw = args;
|
||||
// The debugger reads a generator at its inputs itself, so its lines are the generator's.
|
||||
match name {
|
||||
"convert_program" => return wai_quantum::engine::formats::convert_json(raw),
|
||||
"debug_step" => return wai_quantum::engine::debug::call("step", raw),
|
||||
"debug_branches" => return wai_quantum::engine::debug::call("branches", raw),
|
||||
_ => {}
|
||||
|
|
@ -840,6 +857,30 @@ mod tests {
|
|||
SigningKey::from_bytes(&[5; 32])
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[test]
|
||||
fn a_run_takes_its_program_as_a_source_as_the_service_does() {
|
||||
let listed = tools();
|
||||
for name in ["run_quantum_circuit", "plan_quantum_circuit", "run_on_target"] {
|
||||
let t = listed.as_array().unwrap().iter().find(|t| t["name"] == name).unwrap();
|
||||
assert_eq!(t["inputSchema"]["properties"]["source"], wai_quantum::engine::formats::source_schema(), "{name}");
|
||||
}
|
||||
let bell = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n";
|
||||
let qir = wai_quantum::engine::formats::convert_json(&json!({ "program": bell, "to": "qir" })).unwrap();
|
||||
let call_run = |args: Value| 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();
|
||||
let r = call_run(json!({ "source": { "format": "qir", "program": qir["program"] }, "shots": 64 }));
|
||||
assert_eq!(r["isError"], false, "{r}");
|
||||
let counts = r["structuredContent"]["result"]["counts"].as_object().unwrap();
|
||||
assert!(counts.keys().all(|k| k == "00" || k == "11"), "{r}");
|
||||
assert_eq!(r["structuredContent"]["request"]["source"]["format"], "qir", "the request keeps its source");
|
||||
let bad = call_run(json!({ "source": { "format": "qir", "program": "define void @main() {\nentry:\n call void @__quantum__qis__foo__body(ptr null)\n ret void\n}\n" } }));
|
||||
assert_eq!((bad["isError"].as_bool(), bad["structuredContent"]["codes"].clone()), (Some(true), json!(["Q706", "J001"])), "{bad}");
|
||||
let both = call_run(json!({ "qasm": bell, "source": { "format": "qir", "program": qir["program"] } }));
|
||||
assert_eq!(both["structuredContent"]["code"], "J003", "{both}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_agent_initializes_lists_the_tools_and_runs_a_circuit() {
|
||||
let init = handle(&json!({ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": PROTOCOL } }), 1, &key(), &mut Client::default()).unwrap();
|
||||
|
|
@ -855,7 +896,7 @@ mod tests {
|
|||
let list = handle(&json!({ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }), 1, &key(), &mut Client::default()).unwrap();
|
||||
let names: Vec<&str> = list["result"]["tools"].as_array().unwrap().iter().map(|t| t["name"].as_str().unwrap()).collect();
|
||||
#[allow(unused_mut)]
|
||||
let mut want = vec!["run_quantum_circuit", "plan_quantum_circuit", "lint_qasm", "repair_qasm", "critique_qasm", "check_equivalent", "improve_qasm", "classical_shortcuts", "compile_qasm", "estimate_resources", "draw_circuit", "debug_step", "debug_branches", "verify_quantum_result", "discover_evaluate", "discover_submit", "discover_archive", "novelty_qasm", "discover_novelty", "rewrite_qasm", "converge_cohort", "converge_history", "study_measure", "study_cohort", "taste_rank", "taste_next", "history_commit", "history_changes", "history_blame", "history_log", "list_methods", "qasm_diagnostics", "list_targets", "show_target", "run_on_target", "qec_code", "qec_decode", "qec_threshold", "pulse_schedule", "pulse_check"];
|
||||
let mut want = vec!["run_quantum_circuit", "plan_quantum_circuit", "lint_qasm", "repair_qasm", "critique_qasm", "check_equivalent", "convert_program", "improve_qasm", "classical_shortcuts", "compile_qasm", "estimate_resources", "draw_circuit", "debug_step", "debug_branches", "verify_quantum_result", "discover_evaluate", "discover_submit", "discover_archive", "novelty_qasm", "discover_novelty", "rewrite_qasm", "converge_cohort", "converge_history", "study_measure", "study_cohort", "taste_rank", "taste_next", "history_commit", "history_changes", "history_blame", "history_log", "list_methods", "qasm_diagnostics", "list_targets", "show_target", "run_on_target", "qec_code", "qec_decode", "qec_threshold", "pulse_schedule", "pulse_check"];
|
||||
#[cfg(feature = "providers")]
|
||||
want.extend(["providers_list", "provider_estimate", "run_on_provider"]);
|
||||
assert_eq!(names, want);
|
||||
|
|
@ -1304,6 +1345,12 @@ mod tests {
|
|||
call_tool("critique_qasm", json!({ "qasm": draft }), false, &mut called, &mut hold);
|
||||
call_tool("check_equivalent", json!({ "a": draft, "b": "OPENQASM 3.0;\nqubit[2] q;\ncx q[0], q[1];\nt q[1];\n" }), false, &mut called, &mut hold);
|
||||
call_tool("improve_qasm", json!({ "qasm": draft }), false, &mut called, &mut hold);
|
||||
let qir = call_tool("convert_program", json!({ "program": draft, "to": "qir" }), false, &mut called, &mut hold);
|
||||
call_tool("run_quantum_circuit", json!({ "source": { "format": "qir", "program": qir["program"] }, "shots": 20 }), false, &mut called, &mut hold);
|
||||
call_tool("run_quantum_circuit", json!({ "source": { "format": "qir", "program": "define void @main() {\nentry:\n call void @__quantum__qis__foo__body(ptr null)\n ret void\n}\n" } }), true, &mut called, &mut hold);
|
||||
let jeff = call_tool("convert_program", json!({ "program": qir["program"], "to": "jeff" }), false, &mut called, &mut hold);
|
||||
call_tool("convert_program", json!({ "program_base64": jeff["program_base64"], "to": "qasm" }), false, &mut called, &mut hold);
|
||||
call_tool("convert_program", json!({ "program": "define void @main() {\nentry:\n call void @__quantum__qis__foo__body(ptr null)\n ret void\n}\n", "from": "qir", "to": "qasm" }), true, &mut called, &mut hold);
|
||||
call_tool("classical_shortcuts", json!({ "qasm": draft }), false, &mut called, &mut hold);
|
||||
call_tool("compile_qasm", json!({ "qasm": "OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nrz(0.3) q[0];\ncx q[0], q[1];\n", "epsilon": 1e-3 }), false, &mut called, &mut hold);
|
||||
call_tool("compile_qasm", json!({ "qasm": draft, "basis": "standard", "level": 2, "stages": true }), false, &mut called, &mut hold);
|
||||
|
|
|
|||
|
|
@ -242,8 +242,9 @@ pub fn main(cmd: Cmd) {
|
|||
/// The agent's tools for targets ([`crate::mcp::tools`]).
|
||||
pub fn mcp_tools(job_schema: Value) -> Vec<Value> {
|
||||
let mut run = job_schema;
|
||||
if let Some(r) = run["required"].as_array_mut() {
|
||||
r.push(json!("target"));
|
||||
match run["required"].as_array_mut() {
|
||||
Some(r) => r.push(json!("target")),
|
||||
None => run["required"] = json!(["target"]),
|
||||
}
|
||||
vec![
|
||||
json!({
|
||||
|
|
|
|||
|
|
@ -214,6 +214,18 @@ fn equivalent(a: String, b: String) -> String {
|
|||
equiv::equivalent(&a, &b).to_string()
|
||||
}
|
||||
|
||||
/// A program carried between formats (OpenQASM 3, QIR, jeff as base64),
|
||||
/// checked; a refusal as data, `{error, code, codes, outcome, meaning}`.
|
||||
#[tauri::command]
|
||||
fn convert(request: String) -> String {
|
||||
let answer = serde_json::from_str::<serde_json::Value>(&request).map_err(|e| format!("the request is not JSON: {e}")).and_then(|r| wai_quantum::engine::formats::convert_json(&r));
|
||||
answer.map(|v| v.to_string()).unwrap_or_else(|e| {
|
||||
let mut r = wai_quantum::engine::refusal::refusal_json(&e);
|
||||
r["error"] = serde_json::json!(e);
|
||||
r.to_string()
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn variants(qasm: String) -> String {
|
||||
critique::variants(&qasm).to_string()
|
||||
|
|
@ -964,7 +976,7 @@ fn main() {
|
|||
.plugin(tauri_plugin_updater::Builder::new().build())
|
||||
.manage(Studio { key, job_bytes: job_bytes(), running: Arc::new(Mutex::new(None)), cancelled: Arc::new(Mutex::new(false)) })
|
||||
.manage(PendingUpdate(Mutex::new(None)))
|
||||
.invoke_handler(tauri::generate_handler![run_job, cancel, plan_job, methods, lint, critique, equivalent, variants, shortcuts, compile, verdict, repair, course, course_lesson, course_check, course_hint, estimate, estimate_verify, qec, pulse, draw, layout, debug, visual_edit, picture, verify, signer, save_job, save_program, chat, models, discover_start, discover_submit, discover_search, discover_evaluate, discover_novelty, instantiate, history, locks, novelty, rewrite, taste, converge, study, providers_list, provider_estimate, run_on_provider, targets, target, target_place, answer, telemetry, update_check, update_install])
|
||||
.invoke_handler(tauri::generate_handler![run_job, cancel, plan_job, methods, lint, critique, equivalent, convert, variants, shortcuts, compile, verdict, repair, course, course_lesson, course_check, course_hint, estimate, estimate_verify, qec, pulse, draw, layout, debug, visual_edit, picture, verify, signer, save_job, save_program, chat, models, discover_start, discover_submit, discover_search, discover_evaluate, discover_novelty, instantiate, history, locks, novelty, rewrite, taste, converge, study, providers_list, provider_estimate, run_on_provider, targets, target, target_place, answer, telemetry, update_check, update_install])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("the window opens");
|
||||
}
|
||||
|
|
@ -1254,6 +1266,17 @@ mod tests {
|
|||
assert!(s["summary"].as_str().unwrap().starts_with("Classically easy"), "{s}");
|
||||
}
|
||||
|
||||
/// A QIR module opened in the app reads as OpenQASM 3, checked; one the
|
||||
/// reader does not take is refused as data with its code.
|
||||
#[test]
|
||||
fn a_program_in_another_format_opens_in_the_app() {
|
||||
let qir: Value = serde_json::from_str(&convert(json!({ "program": "qubit[2] q; h q[0]; cx q[0], q[1];", "to": "qir" }).to_string())).unwrap();
|
||||
let back: Value = serde_json::from_str(&convert(json!({ "program": qir["program"], "from": "qir", "to": "qasm" }).to_string())).unwrap();
|
||||
assert_eq!((back["from"].as_str(), back["check"]["verdict"]["verdict"].as_str()), (Some("qir"), Some("equivalent")), "{back}");
|
||||
let bad: Value = serde_json::from_str(&convert(json!({ "program": "define void @main() {\nentry:\n call void @__quantum__qis__foo__body(ptr null)\n ret void\n}\n", "from": "qir", "to": "qasm" }).to_string())).unwrap();
|
||||
assert_eq!(bad["code"], "Q706", "{bad}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_history_records_with_the_app_s_key_and_reads_back() {
|
||||
let key = SigningKey::from_bytes(&[3; 32]);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ A job is JSON:
|
|||
|
||||
| field | meaning |
|
||||
|---|---|
|
||||
| `qasm` | the program: OpenQASM 3, or OpenQASM 2 (required) |
|
||||
| `qasm` | the program: OpenQASM 3, or OpenQASM 2 (required, unless `source` gives it) |
|
||||
| `source` | the program in another format, in place of `qasm`: `{"format": "qir", "program": "…"}` (QIR as LLVM text) or `{"format": "jeff", "program_base64": "…"}`; read to the job's `qasm` before anything else reads the job, the request keeping its source, and a module that does not read refused with its code (`Q700` to `Q721`) and place |
|
||||
| `method` | `auto` (the default) or a method below |
|
||||
| `shots` | measurement shots (default 1024 when nothing else is asked for; at most 1,000,000) |
|
||||
| `seed` | the sampling seed (default 1); the same job and seed give the same counts |
|
||||
|
|
@ -146,6 +147,7 @@ Counts are always seeded samples.
|
|||
| `POST /v1/verify` | `{"request": ..., "result": ...}`: whether the result's receipt seals that request and that result |
|
||||
| `POST /v1/critique` | `{"qasm"}`: the program's measures (gates by kind, two-qubit gates, depth, T count, whether it is Clifford, a modelled fidelity) and its smells, each with its lines |
|
||||
| `POST /v1/equivalent` | `{"a", "b"}`: whether two programs are the same circuit up to a global phase, and how that was decided |
|
||||
| `POST /v1/convert` | `{"to", "program" \| "program_base64", "from"?, "profile"?, "check"?}`: the program carried between OpenQASM 3, QIR and jeff (as base64), with the program as OpenQASM 3, each note with its code, what was read and written, and the check (the output read back and held to the program by the equivalence ladder); a refusal is the reader's, with its code and place ([the formats page](../wai-quantum/docs/formats.md)) |
|
||||
| `POST /v1/improve` | `{"qasm"}`: the program with its smells fixed, each candidate with its measures and checked the same circuit |
|
||||
| `POST /v1/shortcuts` | `{"qasm"}`: each exact classical route to simulating the program, priced on it, and the cheapest for each question |
|
||||
| `POST /v1/compile` | `{"qasm", "epsilon", "level", "basis"}`: the program compiled through checked passes (to Clifford+T within `epsilon`, by default `1e-6`), with a certificate of every pass and the distance, sealed with the service's key in a job's form so `POST /v1/verify` checks it ([the compiler page](../wai-quantum/docs/compiler.md)) |
|
||||
|
|
@ -194,7 +196,7 @@ The six checks answer at once, in the service's own process. Each counts against
|
|||
|
||||
## For agents
|
||||
|
||||
`POST /mcp` serves the service to an agent as Model Context Protocol tools: `run_quantum_circuit`, `run_quantum_set` (a set or a sweep), `dry_run_quantum_job` (the plan, running nothing), `get_quantum_job`, `verify_quantum_receipt`, `critique_qasm`, `check_equivalent`, `improve_qasm`, `classical_shortcuts`, `compile_qasm`, `estimate_resources`, `repair_qasm`, `quantum_service_info`, `qasm_diagnostics`, `list_targets`, `show_target`, `run_on_target`, `quantum_circuit_examples`, `qec_code`, `qec_decode`, `qec_threshold`, `pulse_schedule` and `pulse_check`. A run it makes asks for its verdict, so the request its receipt seals is the job's own `request`; every answer about a program carries its verdict, every refusal its codes, and every tool a versioned output schema. `verify_quantum_receipt` re-runs an estimate. It also serves the engine's resources and prompts, the same as the command line's own server (`wai-quantum mcp`):
|
||||
`POST /mcp` serves the service to an agent as Model Context Protocol tools: `run_quantum_circuit`, `run_quantum_set` (a set or a sweep), `dry_run_quantum_job` (the plan, running nothing), `get_quantum_job`, `verify_quantum_receipt`, `critique_qasm`, `check_equivalent`, `convert_program`, `improve_qasm`, `classical_shortcuts`, `compile_qasm`, `estimate_resources`, `repair_qasm`, `quantum_service_info`, `qasm_diagnostics`, `list_targets`, `show_target`, `run_on_target`, `quantum_circuit_examples`, `qec_code`, `qec_decode`, `qec_threshold`, `pulse_schedule` and `pulse_check`. A run it makes asks for its verdict, so the request its receipt seals is the job's own `request`; every answer about a program carries its verdict, every refusal its codes, and every tool a versioned output schema. `verify_quantum_receipt` re-runs an estimate. It also serves the engine's resources and prompts, the same as the command line's own server (`wai-quantum mcp`):
|
||||
|
||||
- resources: the language the engine reads (`wai-quantum://docs/language`), its diagnostics, the methods with their accuracy classes (their reach in a job's memory here), and worked examples, each with what it must do;
|
||||
- prompts: writing and verifying a circuit for an intent, explaining a result and its receipt, and repairing a program from its diagnostics. Each names this server's own tools.
|
||||
|
|
|
|||
|
|
@ -82,6 +82,16 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"convert": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "https://git.transaction.science/Transaction-Science/open-standards/raw/branch/main/wai/wai-quantum/schemas/tools.v1.json#/$defs/convert"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/refused"
|
||||
}
|
||||
]
|
||||
},
|
||||
"improve": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,28 @@ U=${U%/}
|
|||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
|
||||
post() { curl -sS --max-time 120 -X POST "$U$1" -H 'content-type: application/json' --data-binary "@$2"; }
|
||||
# A client may submit `q` jobs in a window (RateLimit-Policy), and the script
|
||||
# makes more than a default window's 30. So before each POST it reads where it
|
||||
# stands (RateLimit: `r` left, `t` seconds until one more is) from GET /v1/health,
|
||||
# which submits nothing, and with none left it waits for one. CI starts the
|
||||
# service with a larger WAI_QSVC_CLIENT_BURST, so it never waits there; against
|
||||
# production it takes longer, and checks the same things. A dry run counts as a
|
||||
# submission and then answers whether a real one would be taken now, so before
|
||||
# one the script waits for two (`pace 2`).
|
||||
pace() {
|
||||
local need=${1:-1} h r t
|
||||
for _ in $(seq 1 80); do
|
||||
h=$(curl -sS --max-time 30 -D - -o /dev/null "$U/v1/health" | tr -d '\r' | sed -n 's/^[Rr]ate[Ll]imit: //p')
|
||||
r=$(printf '%s' "$h" | sed -n 's/.*r=\([0-9]*\).*/\1/p')
|
||||
t=$(printf '%s' "$h" | sed -n 's/.*t=\([0-9]*\).*/\1/p')
|
||||
if [ -z "$r" ] || [ "$r" -ge "$need" ]; then return 0; fi
|
||||
echo "pace: $r of the $need submissions needed left in this client's window; waiting ${t:-10} s" >&2
|
||||
sleep "$(( ${t:-10} < 1 ? 1 : ${t:-10} ))"
|
||||
done
|
||||
echo "FAIL: no submission came free in this client's window" >&2
|
||||
exit 1
|
||||
}
|
||||
post() { pace; curl -sS --max-time 120 -X POST "$U$1" -H 'content-type: application/json' --data-binary "@$2"; }
|
||||
py() { python3 -I -c "$@"; }
|
||||
# POST /v1/run, then follow a job still queued or running past the service's
|
||||
# wait through GET /v1/jobs/{id}, as a client would: on a loaded host a job
|
||||
|
|
@ -219,8 +240,9 @@ print("examples and openapi: ok,", len(e), "examples,", len(o["paths"]), "paths"
|
|||
# An agent over the Model Context Protocol: initialize, list the tools, run
|
||||
# the first example, and check its receipt. The run states its verdict, so the
|
||||
# request it seals (the job's own `request`) asks for one.
|
||||
mcp() { curl -sS --max-time 120 -X POST "$U/mcp" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' --data-binary "$1"; }
|
||||
mcp() { pace; curl -sS --max-time 120 -X POST "$U/mcp" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' --data-binary "$1"; }
|
||||
mcp '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' > "$tmp/mcp-init.json"
|
||||
pace
|
||||
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 30 -X POST "$U/mcp" -H 'content-type: application/json' --data-binary '{"jsonrpc":"2.0","method":"notifications/initialized"}')
|
||||
mcp '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' > "$tmp/mcp-tools.json"
|
||||
py 'import json,sys
|
||||
|
|
@ -241,16 +263,20 @@ req=json.load(open(sys.argv[2]))["examples"][0]["job"]
|
|||
assert job["request"]==dict(req, verdict=True) and job["verdict"]["level"]=="executed" and job["verdict"]==job["result"]["verdict"], job
|
||||
req=job["request"]
|
||||
print(json.dumps({"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"verify_quantum_receipt","arguments":{"request":req,"result":job["result"]}}}))' "$tmp/mcp-run.json" "$tmp/examples.json" > "$tmp/mcp-verify.json"
|
||||
pace
|
||||
curl -sS --max-time 60 -X POST "$U/mcp" -H 'content-type: application/json' --data-binary "@$tmp/mcp-verify.json" > "$tmp/mcp-verified.json"
|
||||
py 'import json,sys
|
||||
v=json.load(open(sys.argv[1]))["result"]; assert v["structuredContent"]["valid"] is True, v
|
||||
print("mcp run + verify: ok,", json.load(open(sys.argv[2]))["result"]["content"][0]["text"].splitlines()[1])' "$tmp/mcp-verified.json" "$tmp/mcp-run.json"
|
||||
# A host that draws views: the session id that says so, the view's own tool kept from the model, and a page.
|
||||
pace
|
||||
curl -sS -D "$tmp/mcp-views.h" --max-time 60 -X POST "$U/mcp" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
|
||||
--data-binary '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{"extensions":{"io.modelcontextprotocol/ui":{"mimeTypes":["text/html;profile=mcp-app"]}}}}}' > /dev/null
|
||||
sid=$(tr -d '\r' < "$tmp/mcp-views.h" | awk 'tolower($1)=="mcp-session-id:" {print $2}')
|
||||
case "$sid" in wq-views-*) ;; *) echo "no views session id: $sid"; exit 1 ;; esac
|
||||
pace
|
||||
curl -sS --max-time 60 -X POST "$U/mcp" -H 'content-type: application/json' -H "mcp-session-id: $sid" --data-binary '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' > "$tmp/mcp-views-tools.json"
|
||||
pace
|
||||
curl -sS --max-time 60 -X POST "$U/mcp" -H 'content-type: application/json' -H "mcp-session-id: $sid" --data-binary '{"jsonrpc":"2.0","id":3,"method":"resources/read","params":{"uri":"ui://wai-quantum/result"}}' > "$tmp/mcp-views-page.json"
|
||||
py 'import json,sys
|
||||
t={x["name"]: x for x in json.load(open(sys.argv[1]))["result"]["tools"]}
|
||||
|
|
@ -328,6 +354,7 @@ print("device target: ok, placed on", p["layout"], "expected success", round(p["
|
|||
|
||||
# A refusal says why, what to write instead, and ends with its code.
|
||||
py 'import json; print(json.dumps({"qasm": "qubit[1] q; bit c; c = measure q; while (c) { x q; c = measure q; }"}))' > "$tmp/bad.json"
|
||||
pace
|
||||
code=$(curl -sS -o "$tmp/bad.out" -w '%{http_code}' -X POST "$U/v1/jobs" -H 'content-type: application/json' --data-binary "@$tmp/bad.json")
|
||||
[ "$code" = 400 ] || { echo "a bad program got HTTP $code"; exit 1; }
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["code"]=="Q310" and "@wai.max_iterations" in d["error"], d; print("refusal: ok,", d["error"])' "$tmp/bad.out"
|
||||
|
|
@ -344,7 +371,16 @@ py 'import json,sys; c=json.load(open(sys.argv[1]))["candidates"][0]; assert c["
|
|||
py 'import json; print(json.dumps({"a": "OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nh q[0];\ncx q[0], q[1];\n", "b": "OPENQASM 3.0;\nqubit[2] q;\ncx q[0], q[1];\n"}))' > "$tmp/pair.json"
|
||||
post /v1/equivalent "$tmp/pair.json" > "$tmp/equivalent.out"
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["verdict"]=="equivalent" and d["how"]=="tableau", d; print("equivalent: ok, by tableau")' "$tmp/equivalent.out"
|
||||
# A program carried to QIR and back, each conversion checked, and a job
|
||||
# that carries its program as QIR.
|
||||
py 'import json; print(json.dumps({"program": "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n", "to": "qir"}))' > "$tmp/convert.json"
|
||||
post /v1/convert "$tmp/convert.json" > "$tmp/convert.out"
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["ok"] and d["to"]=="qir" and d["written"]["profile"]=="base" and d["check"]["verdict"]["verdict"]=="equivalent", d; print("convert: ok, to QIR,", d["check"]["verdict"]["how"])' "$tmp/convert.out"
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); print(json.dumps({"source": {"format": "qir", "program": d["program"]}, "shots": 50}))' "$tmp/convert.out" > "$tmp/fromqir.json"
|
||||
post /v1/run "$tmp/fromqir.json" > "$tmp/fromqir.out"
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); r=d["result"]; assert d["status"]=="done" and set(r["counts"]) <= {"00","11"} and d["request"]["source"]["format"]=="qir", d; print("a job from QIR: ok,", r["method"])' "$tmp/fromqir.out"
|
||||
py 'import json; print(json.dumps({"qasm": "qubit[1] q;", "thorough": True}))' > "$tmp/thorough.json"
|
||||
pace
|
||||
code=$(curl -sS -o "$tmp/thorough.out" -w '%{http_code}' -X POST "$U/v1/shortcuts" -H 'content-type: application/json' --data-binary "@$tmp/thorough.json")
|
||||
[ "$code" = 422 ] || { echo "a thorough search got HTTP $code"; exit 1; }
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "wai-quantum shortcuts --thorough" in d["error"], d; print("thorough: ok, sent to the command line")' "$tmp/thorough.out"
|
||||
|
|
@ -368,6 +404,7 @@ d=json.load(open(sys.argv[1])); r=d["result"]
|
|||
assert d["status"]=="done" and d["method"]=="exact" and r["accuracy"]["class"]=="bit-exact" and r["compiled"]["distance"] <= 1e-4, d
|
||||
print("compiled job: ok, bit-exact, within", r["compiled"]["distance"])' "$tmp/compiled-job.out"
|
||||
py 'import json; print(json.dumps({"qasm": "qubit[1] q;\nrz(0.3) q[0];\nh q[0];\nrz(0.4) q[0];\n", "epsilon": 1e-13}))' > "$tmp/fine.json"
|
||||
pace
|
||||
code=$(curl -sS -o "$tmp/fine.out" -w '%{http_code}' -X POST "$U/v1/compile" -H 'content-type: application/json' --data-binary "@$tmp/fine.json")
|
||||
[ "$code" = 422 ] || { echo "a too-fine compile got HTTP $code"; exit 1; }
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "wai-quantum compile" in d["error"], d; print("fine compile: ok, sent to the command line")' "$tmp/fine.out"
|
||||
|
|
@ -389,6 +426,7 @@ py 'import json; print(json.dumps({"family": "color", "distances": [3, 5], "p":
|
|||
post /v1/qec/threshold "$tmp/qec-threshold.json" > "$tmp/qec-threshold.out"
|
||||
py 'import json,sys; r=json.load(open(sys.argv[1]))["result"]; assert len(r["points"])==2 and r["below_threshold"][0]["distance_helps"], r; print("qec threshold: ok")' "$tmp/qec-threshold.out"
|
||||
py 'import json; print(json.dumps({"code": "bb:288"}))' > "$tmp/qec-far.json"
|
||||
pace
|
||||
code=$(curl -sS -o "$tmp/qec-far.out" -w '%{http_code}' -X POST "$U/v1/qec/code" -H 'content-type: application/json' --data-binary "@$tmp/qec-far.json")
|
||||
[ "$code" = 422 ] || { echo "a long certification got HTTP $code"; exit 1; }
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "wai-quantum qec code bb:288" in d["error"], d; print("long certification: ok, sent to the command line")' "$tmp/qec-far.out"
|
||||
|
|
@ -415,6 +453,7 @@ print("estimate: ok,", r["estimate"]["physical_qubits"], "physical qubits,", len
|
|||
post /v1/verify "$tmp/estimate.out" > "$tmp/estimate-verify.out"
|
||||
py 'import json,sys; v=json.load(open(sys.argv[1])); assert v["valid"] is True and v["reproduced"] is True and v["receipts"] is True, v; print("estimate verifies and re-runs: ok,", v["estimates"], "receipts")' "$tmp/estimate-verify.out"
|
||||
py 'import json; print(json.dumps({"counts": {"numQubits": 4, "rotationCount": 1000000, "rotationDepth": 10}, "budget": 1e-6}))' > "$tmp/fine-est.json"
|
||||
pace
|
||||
code=$(curl -sS -o "$tmp/fine-est.out" -w '%{http_code}' -X POST "$U/v1/estimate" -H 'content-type: application/json' --data-binary "@$tmp/fine-est.json")
|
||||
[ "$code" = 422 ] || { echo "a too-fine estimate got HTTP $code"; exit 1; }
|
||||
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "wai-quantum estimate" in d["error"], d; print("fine estimate: ok, sent to the command line")' "$tmp/fine-est.out"
|
||||
|
|
@ -440,13 +479,13 @@ post /v1/repair "$tmp/proposal.json" | py 'import json,sys; d=json.load(sys.stdi
|
|||
py 'import json; print(json.dumps({"qasm": "OPENQASM 3.0;\nqubit[1] q;\nrx(0.3) q[0];\n", "method": "stabilizer"}))' > "$tmp/refused.json"
|
||||
post /v1/run "$tmp/refused.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["error"].endswith("[J011]"), d; print("refusal: ok, ends with its code")'
|
||||
|
||||
# The whole script makes 29 submissions (30 on a host with a GPU), within the
|
||||
# 30 a client may make in a window: a check added anywhere must take the place
|
||||
# of one. What follows makes five.
|
||||
# The script makes more submissions than a default window's 30; `pace` (above)
|
||||
# keeps it within whatever window the service gives this client.
|
||||
#
|
||||
# A dry run: the plan, its estimates with their basis, the bounds, and whether
|
||||
# the service would take it; nothing runs.
|
||||
py 'import json; print(json.dumps({"qasm": "OPENQASM 3.0; qubit[30] q; h q[0]; cx q[0], q[29];", "shots": 100, "dry_run": True}))' > "$tmp/dry.json"
|
||||
pace 2
|
||||
post /v1/run "$tmp/dry.json" > "$tmp/dry.out"
|
||||
py 'import json,sys
|
||||
d=json.load(open(sys.argv[1]))
|
||||
|
|
@ -505,6 +544,7 @@ print("sweep (mcp run_quantum_set): ok,", [round(i["result"]["expectations"][0][
|
|||
# refusal comes with its code and the verdict of what was refused (the
|
||||
# program reads; the method named cannot take it).
|
||||
py 'import json; print(json.dumps({"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"dry_run_quantum_job","arguments":{"qasm":"OPENQASM 3.0; qubit[40] q; rx(0.3) q;","amplitudes":["0"*40],"method":"statevector"}}}))' > "$tmp/mcp-dry.json"
|
||||
pace 2
|
||||
mcp "@$tmp/mcp-dry.json" | py 'import json,sys; r=json.load(sys.stdin)["result"]; sc=r["structuredContent"]; assert not r["isError"] and sc["accepted"] is False and sc["refusal"]["code"]=="J011" and sc["verdict"]["level"]=="parsed" and sc["verdict"]["refusal"]["code"]=="J011", r; print("mcp dry run refused: ok,", r["content"][0]["text"][:60]+"…")'
|
||||
|
||||
echo "smoke: every check held at $U"
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue