wai-quantum 0.7.0: Python, bring your own quantum, editors, one OpenQASM 3 reader, compilation, the debugger, device targets, estimates, the verdict, and the version contract #521
403 changed files with 169020 additions and 3060 deletions
2
.github/workflows/wai-conformance.yml
vendored
2
.github/workflows/wai-conformance.yml
vendored
|
|
@ -959,7 +959,7 @@ jobs:
|
|||
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mods="quantum ijson receipt_pins quantum_fabric quantum_source quantum_channel quantum_qudit quantum_receipt"
|
||||
mods="quantum ijson receipt_pins quantum_fabric quantum_source quantum_channel quantum_qudit quantum_receipt engine::synth engine::compile engine::estimate"
|
||||
filters=()
|
||||
for m in $mods; do filters+=("$m::"); done
|
||||
cargo test --locked --target wasm32-wasip2 --features full --lib -- "${filters[@]}" 2>&1 \
|
||||
|
|
|
|||
31
.github/workflows/wai-quantum-cli.yml
vendored
31
.github/workflows/wai-quantum-cli.yml
vendored
|
|
@ -16,12 +16,14 @@ on:
|
|||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-qpu/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-cli.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-qpu/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-cli.yml'
|
||||
|
||||
|
|
@ -69,6 +71,15 @@ jobs:
|
|||
set -euo pipefail
|
||||
cargo test --locked --release 2>&1 | tee "$RUNNER_TEMP/test.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/test.log" || { echo "::error::no test ran"; exit 1; }
|
||||
# Your own providers end to end (tests/providers.rs), against the
|
||||
# reference provider this binary serves, each test by name.
|
||||
for t in a_person_adds_tests_plans_and_runs_on_a_provider_and_the_receipt_verifies \
|
||||
a_run_that_is_not_free_is_refused_until_the_person_confirms_it \
|
||||
a_credential_is_kept_in_a_file_only_its_owner_reads_and_appears_in_nothing_printed \
|
||||
a_provider_over_http_runs_with_its_credential_in_the_header \
|
||||
an_agent_lists_estimates_is_refused_and_runs_only_with_confirm_cost; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/test.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
cargo clippy --locked --release --all-targets -- -D warnings
|
||||
cargo clippy --locked --release --all-targets --no-default-features -- -D warnings
|
||||
- name: The smoke checks
|
||||
|
|
@ -116,6 +127,26 @@ jobs:
|
|||
$n run --demo-key --json --shots 100 < "$RUNNER_TEMP/p.qasm" 2> /dev/null | python3 -c 'import json,sys; j=json.load(sys.stdin); j["result"].pop("elapsed_ms"); j["result"]["receipt"].pop("digest"); j["result"]["receipt"].pop("signature"); print(json.dumps(j, sort_keys=True))' > "$RUNNER_TEMP/native.json"
|
||||
wasmtime run "$w" run --demo-key --json --shots 100 < "$RUNNER_TEMP/p.qasm" 2> /dev/null | python3 -c 'import json,sys; j=json.load(sys.stdin); j["result"].pop("elapsed_ms"); j["result"]["receipt"].pop("digest"); j["result"]["receipt"].pop("signature"); print(json.dumps(j, sort_keys=True))' > "$RUNNER_TEMP/wasi.json"
|
||||
cmp "$RUNNER_TEMP/native.json" "$RUNNER_TEMP/wasi.json" || { echo "::error::a run's result differs under wasmtime"; exit 1; }
|
||||
# A compile to Clifford+T (rotation synthesis in exact and fixed-point
|
||||
# arithmetic, the passes, the certificate and its seal): byte for byte.
|
||||
printf 'OPENQASM 3.0; qubit[2] q; h q[0]; rz(0.3) q[0]; cx q[0], q[1]; ry(1.1) q[1]; cp(0.7) q[0], q[1];' > "$RUNNER_TEMP/angles.qasm"
|
||||
$n compile --demo-key --json --level 2 --epsilon 1e-8 < "$RUNNER_TEMP/angles.qasm" > "$RUNNER_TEMP/native-compile.json" 2> /dev/null
|
||||
wasmtime run "$w" compile --demo-key --json --level 2 --epsilon 1e-8 < "$RUNNER_TEMP/angles.qasm" > "$RUNNER_TEMP/wasi-compile.json" 2> /dev/null
|
||||
cmp "$RUNNER_TEMP/native-compile.json" "$RUNNER_TEMP/wasi-compile.json" || { echo "::error::a compile differs under wasmtime"; exit 1; }
|
||||
# A run on a device target: the layout search, the noise derived and
|
||||
# the density matrix, the same bits.
|
||||
for t in synthetic-line-5 synthetic-all-5; do
|
||||
$n run --demo-key --json --shots 100 --target $t < "$RUNNER_TEMP/p.qasm" 2> /dev/null | python3 -c 'import json,sys; j=json.load(sys.stdin); j["result"]["receipt"].pop("digest"); j["result"]["receipt"].pop("signature"); print(json.dumps(j, sort_keys=True))' > "$RUNNER_TEMP/native-$t.json"
|
||||
wasmtime run "$w" run --demo-key --json --shots 100 --target $t < "$RUNNER_TEMP/p.qasm" 2> /dev/null | python3 -c 'import json,sys; j=json.load(sys.stdin); j["result"]["receipt"].pop("digest"); j["result"]["receipt"].pop("signature"); print(json.dumps(j, sort_keys=True))' > "$RUNNER_TEMP/wasi-$t.json"
|
||||
cmp "$RUNNER_TEMP/native-$t.json" "$RUNNER_TEMP/wasi-$t.json" || { echo "::error::a run on $t differs under wasmtime"; exit 1; }
|
||||
done
|
||||
# A resource estimate (the counts, each rotation's synthesis, the
|
||||
# planar model's factory search and the frontier, every receipt and
|
||||
# the seal): byte for byte.
|
||||
printf 'OPENQASM 3.0; qubit[4] q; h q; ctrl(3) @ x q[0], q[1], q[2], q[3]; rz(0.3) q[0]; ry(1.1) q[2]; t q[1];' > "$RUNNER_TEMP/est.qasm"
|
||||
$n estimate --demo-key --json --qubit us-e3 < "$RUNNER_TEMP/est.qasm" > "$RUNNER_TEMP/native-estimate.json" 2> /dev/null
|
||||
wasmtime run "$w" estimate --demo-key --json --qubit us-e3 < "$RUNNER_TEMP/est.qasm" > "$RUNNER_TEMP/wasi-estimate.json" 2> /dev/null
|
||||
cmp "$RUNNER_TEMP/native-estimate.json" "$RUNNER_TEMP/wasi-estimate.json" || { echo "::error::an estimate differs under wasmtime"; exit 1; }
|
||||
echo "the WASI component's output equals the native build's"
|
||||
|
||||
cli-macos:
|
||||
|
|
|
|||
289
.github/workflows/wai-quantum-contract.yml
vendored
Normal file
289
.github/workflows/wai-quantum-contract.yml
vendored
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
name: wai-quantum contract
|
||||
|
||||
# The version and deprecation contract (wai/wai-quantum/VERSIONING.md), on
|
||||
# Linux:
|
||||
#
|
||||
# - api: cargo-semver-checks, built from crates.io at a pinned version,
|
||||
# compares wai-quantum, wai-quantum-cli and wai-quantum-qpu with the last
|
||||
# version of each on crates.io (the baselines below). It checks every change as if for a minor
|
||||
# release, so that each breaking change is listed, and fails only on a
|
||||
# breaking change made without a major bump. Before 1.0 the first non-zero
|
||||
# component is the major (0.6.16 to 0.7.0 is a major bump). A step warns
|
||||
# when crates.io holds a newer version than a baseline here, so a baseline
|
||||
# does not go stale unseen.
|
||||
# - schemas: the schema tests, each by name. The engine's: every schema file
|
||||
# reads and names itself, every method's job and every engine tool's answer
|
||||
# follows its schema with no member it does not name, and receipts issued
|
||||
# before results named their engine and schema still verify, their digests
|
||||
# pinned. Both MCP servers': every tool's answer follows its outputSchema,
|
||||
# the committed tool lists (wai-quantum-cli/docs/local-mcp.json and
|
||||
# service-mcp.json) are the live lists, the agent docs are what the binary
|
||||
# generates, and initialize reports the versions. The job service's job in
|
||||
# each status. The provider protocol's messages and answers. Then a full
|
||||
# JSON Schema implementation (wai/wai-quantum/ci/check_schemas.py) reads
|
||||
# every schema file and both tool lists, and holds a release build's
|
||||
# answers to them.
|
||||
# - policy: every README of a WAI Quantum package links the policy, and the
|
||||
# deprecations page's table is well formed.
|
||||
#
|
||||
# The receipts' legacy pins and the conformance corpora run where they always
|
||||
# have (wai-energy-receipts.yml, wai-conformance.yml).
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-service/**'
|
||||
- 'wai/wai-quantum-qpu/**'
|
||||
- 'wai/wai-quantum-py/README.md'
|
||||
- 'wai/wai-quantum-desktop/README.md'
|
||||
- 'wai/quantum-studio/README.md'
|
||||
- 'wai/tools/wai-quantum-editor/README.md'
|
||||
- 'wai/tools/tree-sitter-openqasm/README.md'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-contract.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-service/**'
|
||||
- 'wai/wai-quantum-qpu/**'
|
||||
- 'wai/wai-quantum-py/README.md'
|
||||
- 'wai/wai-quantum-desktop/README.md'
|
||||
- 'wai/quantum-studio/README.md'
|
||||
- 'wai/tools/wai-quantum-editor/README.md'
|
||||
- 'wai/tools/tree-sitter-openqasm/README.md'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-contract.yml'
|
||||
|
||||
jobs:
|
||||
# Does this pull request's own diff touch the paths above? This forge matches a
|
||||
# workflow's `paths:` against the push, so a merge of main into a branch fires the
|
||||
# workflow whatever the pull request changes; every job here waits on this answer.
|
||||
# A push to main, or anything the script cannot determine, answers `true`
|
||||
# (scripts/pr-touches-paths.py).
|
||||
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-contract.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches the wai-quantum contract: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
api:
|
||||
name: API compatibility · linux
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: linux
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
# The last version of each on crates.io. Raise each when a release is published.
|
||||
WAI_QUANTUM_BASELINE: "0.6.16"
|
||||
WAI_QUANTUM_CLI_BASELINE: "0.1.4"
|
||||
WAI_QUANTUM_QPU_BASELINE: "0.2.0"
|
||||
# Built from its source on crates.io, at this version.
|
||||
SEMVER_CHECKS: "0.51.0"
|
||||
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"
|
||||
- name: Install cargo-semver-checks ${{ env.SEMVER_CHECKS }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo install cargo-semver-checks --version "$SEMVER_CHECKS" --locked --root "$RUNNER_TEMP/semver"
|
||||
echo "$RUNNER_TEMP/semver/bin" >> "$GITHUB_PATH"
|
||||
- name: The baselines are the last versions published
|
||||
shell: bash
|
||||
working-directory: ${{ runner.temp }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for pair in "wai-quantum $WAI_QUANTUM_BASELINE" "wai-quantum-cli $WAI_QUANTUM_CLI_BASELINE" "wai-quantum-qpu $WAI_QUANTUM_QPU_BASELINE"; do
|
||||
set -- $pair
|
||||
latest=$(cargo info "$1" 2>/dev/null | sed -n 's/^version: *\([^ ]*\).*/\1/p' | head -1 || true)
|
||||
if [ -z "$latest" ]; then
|
||||
echo "::warning::crates.io did not say which version of $1 is the last; the check runs against $2"
|
||||
elif [ "$latest" != "$2" ]; then
|
||||
echo "::warning::crates.io's last version of $1 is $latest, and this workflow's baseline is $2: raise the baseline"
|
||||
else
|
||||
echo "$1: the baseline $2 is the last version on crates.io"
|
||||
fi
|
||||
done
|
||||
- name: API compatibility, against the last versions published
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# The major of a version: the first non-zero component (0.6.16 -> 0.6, 1.2.3 -> 1).
|
||||
major() { IFS=. read -r a b _ <<< "$1"; if [ "$a" = 0 ]; then echo "0.$b"; else echo "$a"; fi; }
|
||||
# Every change is checked as if for a minor release, so that each breaking
|
||||
# change is listed; a breaking change fails the step only when the major
|
||||
# is still the baseline's. A build that fails is a failure either way.
|
||||
check() {
|
||||
local dir=$1 base=$2 cur log
|
||||
cur=$(sed -n 's/^version *= *"\([^"]*\)".*/\1/p' "$dir/Cargo.toml" | head -1)
|
||||
log="$RUNNER_TEMP/semver-$(basename "$dir").log"
|
||||
echo "== $dir: $base -> $cur, the major $(major "$base") -> $(major "$cur")"
|
||||
if cargo semver-checks check-release --manifest-path "$dir/Cargo.toml" --baseline-version "$base" --release-type minor 2>&1 | tee "$log"; then
|
||||
echo "$dir: no breaking change against $base"
|
||||
elif ! grep -q 'semver requires new major version' "$log"; then
|
||||
echo "::error::$dir: the check did not run to its end (above)"
|
||||
return 1
|
||||
elif [ "$(major "$cur")" != "$(major "$base")" ]; then
|
||||
echo "::warning::$dir: breaking changes against $base, listed above; allowed, as the major is bumped to $(major "$cur")"
|
||||
else
|
||||
echo "::error::$dir: a breaking change against $base, listed above, without a major bump: raise $(major "$base") (before 1.0, the 0.y component), and say what to do instead in the changelog"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
r=0
|
||||
check wai/wai-quantum "$WAI_QUANTUM_BASELINE" || r=1
|
||||
check wai/wai-quantum-cli "$WAI_QUANTUM_CLI_BASELINE" || r=1
|
||||
check wai/wai-quantum-qpu "$WAI_QUANTUM_QPU_BASELINE" || r=1
|
||||
exit $r
|
||||
|
||||
schemas:
|
||||
name: schemas and the committed tool lists · 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, and uv
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH="$HOME/.local/bin:$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
|
||||
command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
- name: The engine's schemas, and receipts issued before
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --no-default-features --features quantum_engine,quantum_receipt --lib engine::schema:: 2>&1 | tee "$RUNNER_TEMP/engine.log"
|
||||
for t in every_schema_reads_names_itself_and_refers_only_to_what_is_there \
|
||||
the_checker_reads_the_subset_it_names_and_refuses_what_it_should \
|
||||
every_check_s_answer_follows_its_schema \
|
||||
every_method_s_job_follows_the_job_schemas \
|
||||
a_new_result_names_its_engine_and_schema_and_its_receipt_binds_them \
|
||||
receipts_issued_before_results_named_them_still_verify; do
|
||||
grep -q "^test engine::schema::tests::$t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
- name: The command line's MCP server, its committed tool list and its docs
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-cli
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --bin wai-quantum 2>&1 | tee "$RUNNER_TEMP/cli.log"
|
||||
for t in mcp::tests::the_schemas_read_and_name_themselves \
|
||||
mcp::tests::every_tool_s_answer_follows_its_output_schema \
|
||||
mcp::tests::the_committed_tool_list_is_this_server_s_live_list \
|
||||
mcp::tests::an_agent_initializes_lists_the_tools_and_runs_a_circuit \
|
||||
guide::tests::the_committed_docs_are_what_the_binary_generates \
|
||||
guide::tests::the_docs_list_exactly_the_servers_tools_and_name_no_version \
|
||||
tests::the_command_line_parses_as_documented; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/cli.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
- name: The job service's MCP server, its committed tool list and its job
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-service
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release -- mcp:: jobs:: 2>&1 | tee "$RUNNER_TEMP/service.log"
|
||||
for t in mcp::tests::the_schemas_read_and_the_versions_are_reported \
|
||||
mcp::tests::every_tool_s_answer_follows_its_output_schema \
|
||||
mcp::tests::every_tool_has_a_schema_and_a_description \
|
||||
mcp::tests::the_command_line_s_snapshot_is_this_server_s_live_list \
|
||||
jobs::tests::a_job_s_form_follows_the_job_schema; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/service.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
- name: The provider protocol's messages
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-qpu
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --test protocol_schema 2>&1 | tee "$RUNNER_TEMP/qpu.log"
|
||||
for t in the_schema_names_the_protocol_s_own_constants every_message_and_answer_follows_the_protocol_s_schema; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/qpu.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
# A second implementation of JSON Schema, sharing no code with the engine's
|
||||
# checker: every schema file and both tool lists valid 2020-12 schemas, every
|
||||
# reference resolving, and a release build's answers holding to them.
|
||||
- name: The schemas, read by a full JSON Schema implementation
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
(cd wai/wai-quantum-cli && cargo build --locked --release)
|
||||
uv venv -q --python 3.12 "$RUNNER_TEMP/schemas"
|
||||
uv pip install -q --python "$RUNNER_TEMP/schemas/bin/python" --require-hashes -r wai/wai-quantum-py/tests/requirements.lock
|
||||
"$RUNNER_TEMP/schemas/bin/python" -I wai/wai-quantum/ci/check_schemas.py wai wai/wai-quantum-cli/target/release/wai-quantum
|
||||
|
||||
policy:
|
||||
name: the policy is linked, and the deprecations page reads
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: linux
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Every README of a WAI Quantum package links the policy
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for f in wai/wai-quantum/README.md wai/wai-quantum-cli/README.md wai/wai-quantum-service/README.md \
|
||||
wai/wai-quantum-qpu/README.md wai/wai-quantum-py/README.md wai/wai-quantum-desktop/README.md \
|
||||
wai/quantum-studio/README.md wai/tools/wai-quantum-editor/README.md wai/tools/tree-sitter-openqasm/README.md; do
|
||||
grep -q 'wai/wai-quantum/VERSIONING.md\|(VERSIONING.md)' "$f" || { echo "::error::$f does not link the policy (wai/wai-quantum/VERSIONING.md)"; exit 1; }
|
||||
done
|
||||
echo "every README links the policy"
|
||||
- name: The deprecations page's table is well formed
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 -I - wai/wai-quantum/DEPRECATIONS.md <<'EOF'
|
||||
import re, sys
|
||||
lines = open(sys.argv[1], encoding="utf-8").read().splitlines()
|
||||
head = "| Package | Item | Deprecated in | Replacement | Removed in |"
|
||||
assert head in lines, "the table's header is " + head
|
||||
at = lines.index(head)
|
||||
assert re.fullmatch(r"\|(---\|){5}", lines[at + 1]), lines[at + 1]
|
||||
semver = re.compile(r"\d+\.\d+\.\d+")
|
||||
rows = []
|
||||
for line in lines[at + 2:]:
|
||||
if not line.startswith("|"):
|
||||
break
|
||||
cells = [c.strip() for c in line.strip("|").split("|")]
|
||||
assert len(cells) == 5 and all(cells[:4]), f"a row names its package, item, version and replacement: {line}"
|
||||
assert semver.fullmatch(cells[2]), f"deprecated in a version: {line}"
|
||||
assert cells[4] == "" or semver.fullmatch(cells[4]), f"removed in a version, or not yet: {line}"
|
||||
rows.append(cells)
|
||||
print(f"{len(rows)} deprecated item(s) listed")
|
||||
EOF
|
||||
8
.github/workflows/wai-quantum-dsp.yml
vendored
8
.github/workflows/wai-quantum-dsp.yml
vendored
|
|
@ -177,16 +177,20 @@ jobs:
|
|||
export CARGO_TARGET_HEXAGON_UNKNOWN_LINUX_MUSL_RUNNER="$cache/qemu-hexagon-$HEXAGON_EMULATOR_VERSION -L $tc/target/hexagon-unknown-linux-musl"
|
||||
export CC_hexagon_unknown_linux_musl=hexagon-linux-musl-clang AR_hexagon_unknown_linux_musl=hexagon-linux-musl-ar
|
||||
logs="$cache/logs"; mkdir -p "$logs"
|
||||
# FEATURES names the build (full, unless a step says otherwise).
|
||||
t() {
|
||||
name="$1"; shift
|
||||
timeout 2700 cargo test --locked --release -j 6 -Zbuild-std -Zbuild-std-features=system-llvm-libunwind \
|
||||
--target hexagon-unknown-linux-musl --features full "$@" 2>&1 | tee "$logs/$name.log"
|
||||
--target hexagon-unknown-linux-musl --features "${FEATURES:-full}" "$@" 2>&1 | tee "$logs/$name.log"
|
||||
}
|
||||
t bit_identity --test bit_identity -- --test-threads=1
|
||||
grep -qE '^test result: ok\. 23 passed; 0 failed' "$logs/bit_identity.log" || { echo "::error::the 23 bit-identity digests did not all pass"; exit 1; }
|
||||
t frame --test frame_reference -- --test-threads=1
|
||||
grep -qE '^test result: ok\. 2 passed; 0 failed' "$logs/frame.log" || { echo "::error::the fixtures did not pass"; exit 1; }
|
||||
t lib --lib -- quantum:: quantum_fabric:: ijson:: quantum_receipt quantum_energy quantum_qbom merkle
|
||||
# The library's tests with the features their modules need, not full: the
|
||||
# whole engine's test binary is past the processor's direct-call reach
|
||||
# (R_HEX_B22_PCREL, ±8 MiB), and these modules need none of the rest.
|
||||
FEATURES="quantum_fabric quantum_receipt quantum_qbom" t lib --lib -- quantum:: quantum_fabric:: ijson:: quantum_receipt quantum_energy quantum_qbom merkle
|
||||
grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$logs/lib.log" || { echo "::error::the byte-pinning library tests did not pass"; exit 1; }
|
||||
- name: The vector-unit member's tests
|
||||
shell: bash
|
||||
|
|
|
|||
204
.github/workflows/wai-quantum-editors.yml
vendored
Normal file
204
.github/workflows/wai-quantum-editors.yml
vendored
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
name: wai-quantum editors
|
||||
|
||||
# The engine in editors:
|
||||
# - the language service (wai/wai-quantum/src/engine/editor): its unit tests,
|
||||
# each module by name, on Linux and macOS;
|
||||
# - the language server, `wai-quantum lsp`, driven over standard input and
|
||||
# output by a scripted session from initialize to exit (tests/lsp.rs), on
|
||||
# Linux and macOS;
|
||||
# - the debugger (wai/wai-quantum/src/engine/debug.rs, with the visual edits
|
||||
# and the statistical tests beside it), each module by name, and the debug
|
||||
# adapter, `wai-quantum dap`, driven by scripted sessions from initialize
|
||||
# to disconnect (tests/dap.rs), on Linux and macOS;
|
||||
# - `wai-quantum fmt` on every program in the repository: formatting the
|
||||
# formatted program changes nothing, and the engine draws the same circuit;
|
||||
# - the tree-sitter grammar (wai/tools/tree-sitter-openqasm): regenerated
|
||||
# with the pinned command line and identical to the committed parser, its
|
||||
# corpus and highlighting tests, and every program in the repository's
|
||||
# conformance material and examples parsed with no error;
|
||||
# - the editor extension (wai/tools/wai-quantum-editor): built, packaged as a
|
||||
# .vsix with the pinned packaging tool, and checked (its manifest against
|
||||
# the server, its highlighting, its message when the command line is
|
||||
# missing, the other editors' configurations, and the package's files);
|
||||
# - the extension for editors with WebAssembly extensions, built for
|
||||
# wasm32-wasip2.
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/tools/tree-sitter-openqasm/**'
|
||||
- 'wai/tools/wai-quantum-editor/**'
|
||||
- 'wai/quantum-studio/src/examples.js'
|
||||
- 'wai/quantum-ops-conformance/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-editors.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/tools/tree-sitter-openqasm/**'
|
||||
- 'wai/tools/wai-quantum-editor/**'
|
||||
- 'wai/quantum-studio/src/examples.js'
|
||||
- 'wai/quantum-ops-conformance/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-editors.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-editors.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches the editors' support: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
editors-linux:
|
||||
name: editors · linux
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: linux
|
||||
timeout-minutes: 60
|
||||
# The grammar's tree-sitter command (from npm, a prebuilt binary) needs glibc
|
||||
# 2.39, which the runner's default image (act-22.04, glibc 2.35) lacks; this
|
||||
# image has it, as wai-neural-e2e.yml's job does for its libraries.
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-24.04
|
||||
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"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
# The filters are module paths, and a filter that matches nothing passes, so
|
||||
# each module must show a test that passed.
|
||||
- name: The language service's tests
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --features full --lib engine::editor:: 2>&1 | tee "$RUNNER_TEMP/service.log"
|
||||
for m in lex index gates format tests; do
|
||||
grep -qE "^test engine::editor::$m::.* \.\.\. ok$" "$RUNNER_TEMP/service.log" || { echo "::error::no test of engine::editor::$m ran"; exit 1; }
|
||||
done
|
||||
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/service.log"
|
||||
- name: The language server over standard input and output, and the verbs' parsing
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-cli
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --test lsp 2>&1 | tee "$RUNNER_TEMP/lsp.log"
|
||||
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/lsp.log" || { echo "::error::the protocol session did not pass"; exit 1; }
|
||||
cargo test --locked --release --bin wai-quantum -- lsp:: the_command_line_parses_as_documented 2>&1 | tee "$RUNNER_TEMP/unit.log"
|
||||
grep -qE '^test result: ok\. 4 passed; 0 failed' "$RUNNER_TEMP/unit.log" || { echo "::error::the server's unit tests did not all run"; exit 1; }
|
||||
cargo build --locked --release
|
||||
- name: The debugger's tests, and the debug adapter over standard input and output
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd wai/wai-quantum
|
||||
cargo test --locked --features full --lib -- engine::debug:: engine::visual:: engine::stats:: 2>&1 | tee "$RUNNER_TEMP/debug.log"
|
||||
for m in debug visual stats; do
|
||||
grep -qE "^test engine::$m::.* \.\.\. ok$" "$RUNNER_TEMP/debug.log" || { echo "::error::no test of engine::$m ran"; exit 1; }
|
||||
done
|
||||
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/debug.log"
|
||||
cd ../wai-quantum-cli
|
||||
cargo test --locked --release --test dap 2>&1 | tee "$RUNNER_TEMP/dap.log"
|
||||
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/dap.log" || { echo "::error::the debug adapter's sessions did not pass"; exit 1; }
|
||||
- name: The grammar, regenerated as committed; its corpus, its highlighting, and every program in the repository
|
||||
shell: bash
|
||||
working-directory: wai/tools/tree-sitter-openqasm
|
||||
run: |
|
||||
set -euo pipefail
|
||||
npm ci --no-audit --no-fund
|
||||
npx tree-sitter generate --abi 14
|
||||
git diff --exit-code -- src || { echo "::error::src/ is not what grammar.js generates: regenerate and commit it"; exit 1; }
|
||||
npx tree-sitter test
|
||||
node script/check-programs.mjs --out "$RUNNER_TEMP/programs"
|
||||
- name: wai-quantum fmt on every program in the repository
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
w="$PWD/wai/wai-quantum-cli/target/release/wai-quantum"
|
||||
n=0
|
||||
for f in "$RUNNER_TEMP"/programs/*.qasm; do
|
||||
"$w" fmt "$f" > "$RUNNER_TEMP/once.qasm"
|
||||
"$w" fmt "$RUNNER_TEMP/once.qasm" > "$RUNNER_TEMP/twice.qasm"
|
||||
cmp -s "$RUNNER_TEMP/once.qasm" "$RUNNER_TEMP/twice.qasm" || { echo "::error::formatting $f again changed it"; diff "$RUNNER_TEMP/once.qasm" "$RUNNER_TEMP/twice.qasm" || true; exit 1; }
|
||||
# The engine draws the formatted program as it draws the program, or refuses
|
||||
# both (a refusal names a line, which formatting may move).
|
||||
args=(); grep -qE '^\s*input\s+u?int' "$f" && args=(--input n=5)
|
||||
a_out=$("$w" "${args[@]}" draw < "$f" 2>/dev/null) && a=0 || a=$?
|
||||
b_out=$("$w" "${args[@]}" draw < "$RUNNER_TEMP/once.qasm" 2>/dev/null) && b=0 || b=$?
|
||||
[ "$a" = "$b" ] || { echo "::error::the engine reads $f (status $a) and its formatted form (status $b) differently"; exit 1; }
|
||||
[ "$a" != 0 ] || [ "$a_out" = "$b_out" ] || { echo "::error::the engine draws the formatted $f differently"; diff <(echo "$a_out") <(echo "$b_out") || true; exit 1; }
|
||||
n=$((n + 1))
|
||||
done
|
||||
[ "$n" -ge 20 ] || { echo "::error::only $n programs were formatted"; exit 1; }
|
||||
echo "fmt: $n programs, each stable, each drawn the same or refused alike"
|
||||
- name: The editor extension, packaged and checked
|
||||
shell: bash
|
||||
working-directory: wai/tools/wai-quantum-editor
|
||||
run: |
|
||||
set -euo pipefail
|
||||
npm ci --no-audit --no-fund
|
||||
npm run package < /dev/null
|
||||
WAI_QUANTUM_BIN="$GITHUB_WORKSPACE/wai/wai-quantum-cli/target/release/wai-quantum" node test/check.mjs --vsix wai-quantum.vsix
|
||||
- name: The extension for editors with WebAssembly extensions, for wasm32-wasip2
|
||||
shell: bash
|
||||
working-directory: wai/tools/wai-quantum-editor/editors/extension
|
||||
run: cargo build --locked --release --target wasm32-wasip2
|
||||
|
||||
editors-macos:
|
||||
name: editors · macos
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: macos
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
# launchd's PATH omits cargo on the macOS host runner.
|
||||
- name: Put cargo on PATH
|
||||
shell: bash
|
||||
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
- name: The language service's tests
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
nice -n 10 cargo test --locked --features full --lib engine::editor:: 2>&1 | tee "$RUNNER_TEMP/service.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/service.log"
|
||||
- name: The language server over standard input and output
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-cli
|
||||
run: |
|
||||
set -euo pipefail
|
||||
nice -n 10 cargo test --locked --release --test lsp 2>&1 | tee "$RUNNER_TEMP/lsp.log"
|
||||
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/lsp.log" || { echo "::error::the protocol session did not pass"; exit 1; }
|
||||
nice -n 10 cargo test --locked --release --test dap 2>&1 | tee "$RUNNER_TEMP/dap.log"
|
||||
grep -qE '^test result: ok\. 2 passed; 0 failed' "$RUNNER_TEMP/dap.log" || { echo "::error::the debug adapter's sessions did not pass"; exit 1; }
|
||||
93
.github/workflows/wai-quantum-estimate.yml
vendored
Normal file
93
.github/workflows/wai-quantum-estimate.yml
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
name: wai-quantum resource estimation
|
||||
|
||||
# Resource estimation from programs (wai/wai-quantum/src/engine/estimate/):
|
||||
# the logical counts against programs whose counts are known exactly, the
|
||||
# ladders through ancillas against the gates they replace on dense unitaries,
|
||||
# each rotation's T count against its synthesised word, the interchange
|
||||
# documents against the format's schema and a self-made fixture, the
|
||||
# frontier, the seals, and the planar model and its receipts
|
||||
# (quantum_resource, quantum_resource_receipt) beside them.
|
||||
#
|
||||
# In a release build the calibration test measures every point of the
|
||||
# decoders' table again (the rotated surface-code memory experiment, decoded
|
||||
# by exact matching and by union-find on the same shots), so the code model
|
||||
# the estimate calibrates from is held to what the decoders measure; a debug
|
||||
# build measures one point. The other platforms run these tests in the
|
||||
# crate's suites (wai-energy-receipts.yml, debug) and under wasm32-wasip2
|
||||
# (wai-conformance.yml).
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-estimate.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-estimate.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-estimate.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches resource estimation: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
native:
|
||||
name: estimation and calibration · linux, release
|
||||
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 estimate, the planar model and their receipts
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --lib -- engine::estimate quantum_resource 2>&1 | tee "$RUNNER_TEMP/estimate.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$RUNNER_TEMP/estimate.log" || { echo "::error::the estimate's tests did not pass"; exit 1; }
|
||||
for t in engine::estimate::calibration::tests::the_table_is_what_the_decoders_measure \
|
||||
engine::estimate::count::tests::ladders_through_ancillas_are_the_controlled_gates_they_replace \
|
||||
engine::estimate::count::tests::the_counts_of_programs_whose_counts_are_known_exactly \
|
||||
engine::estimate::interchange::tests::the_fixture_meets_the_schema_and_its_totals_are_its_children_s \
|
||||
engine::estimate::tests::an_estimate_is_sealed_verifies_and_a_changed_one_does_not \
|
||||
quantum_resource::tests::the_summary_rows_are_reproduced \
|
||||
quantum_resource_receipt::tests::a_counted_program_binds_its_digest_and_its_epsilon; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/estimate.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
- name: The engine without receipts still builds the estimate
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: cargo check --locked --no-default-features --features quantum_engine --lib
|
||||
147
.github/workflows/wai-quantum-lang.yml
vendored
Normal file
147
.github/workflows/wai-quantum-lang.yml
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
name: wai-quantum OpenQASM reader
|
||||
|
||||
# The OpenQASM reader every surface uses (wai/wai-quantum/src/qasm.rs and
|
||||
# src/qasm/): its unit tests (the lexer, the parser, the elaborator, the
|
||||
# diagnostic table and the page that documents it, every modifier against the
|
||||
# matrix it must equal, every condition compiled to steps against every value
|
||||
# of its bits), and the OpenQASM 3 conformance corpus
|
||||
# (wai/quantum-conformance/qasm3/: the specification's example programs and a
|
||||
# program for each construct, each with what the reader must do with it).
|
||||
#
|
||||
# The corpus 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. The browser build runs the corpus too
|
||||
# (wai-web-wasm.yml, wai-web's wasm32 tests). The reader is also built without
|
||||
# the lowerings (features quantum_lang and quantum_toolchain), as the edge
|
||||
# component builds it.
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/quantum-conformance/qasm3/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-lang.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/quantum-conformance/qasm3/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-lang.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-lang.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches the OpenQASM reader: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
native:
|
||||
name: reader and corpus · 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 reader's unit tests
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --lib qasm 2>&1 | tee "$RUNNER_TEMP/qasm.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$RUNNER_TEMP/qasm.log" || { echo "::error::the reader's tests did not pass"; exit 1; }
|
||||
for m in qasm::diag qasm::lex qasm::parse qasm::value qasm::lang_tests qasm::tests quantum_toolchain::tests::qasm_round_trip; do
|
||||
grep -q "^test $m.* \.\.\. ok$" "$RUNNER_TEMP/qasm.log" || { echo "::error::no test of $m ran"; exit 1; }
|
||||
done
|
||||
- name: The conformance corpus
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --test qasm3_conformance 2>&1 | tee "$RUNNER_TEMP/corpus.log"
|
||||
grep -q 'test result: ok. 2 passed; 0 failed' "$RUNNER_TEMP/corpus.log" || { echo "::error::the corpus did not pass"; exit 1; }
|
||||
- name: The reader without the lowerings
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo check --locked --no-default-features --features quantum_lang --lib
|
||||
cargo check --locked --no-default-features --features quantum_toolchain --lib
|
||||
|
||||
wasip2:
|
||||
name: corpus 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 corpus's files has no wasip2 build; the one that runs the
|
||||
# cases from the compiled-in bundle does.
|
||||
- name: The conformance corpus 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 qasm3_conformance 2>&1 | tee "$RUNNER_TEMP/wasip2.log"
|
||||
grep -q 'test result: ok. 1 passed; 0 failed' "$RUNNER_TEMP/wasip2.log" || { echo "::error::the corpus did not pass under wasip2"; exit 1; }
|
||||
213
.github/workflows/wai-quantum-py-release.yml
vendored
Normal file
213
.github/workflows/wai-quantum-py-release.yml
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
name: wai-quantum for Python, release wheels
|
||||
|
||||
# On a tag wai-quantum-cli-v<version> (the command line's release), builds the Python
|
||||
# package's wheels (wai/wai-quantum-py) and attaches them to the same forge release,
|
||||
# each with its SHA-256. One abi3 wheel per platform serves every Python from 3.9 on:
|
||||
# macOS arm64 and x86_64 (the x86_64 one cross-built on the Apple-silicon runner);
|
||||
# Linux x86_64 and arm64, manylinux2014 (glibc 2.17), linked with zig so the
|
||||
# runner's newer glibc does not leak into the wheel;
|
||||
# Windows x86_64.
|
||||
# Each wheel that runs on its runner is installed alone on Python 3.9 in a fresh venv
|
||||
# and runs tests/smoke.py before it is attached. Nothing is published to a package
|
||||
# index.
|
||||
#
|
||||
# Uploads go to the forge directly over the private network (FORGE_API), never through
|
||||
# the public tunnel. A runner that is down leaves its platform's wheel missing: the
|
||||
# release lists what each build attached.
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['wai-quantum-cli-v*']
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
FORGE_API: http://100.64.224.0:3400/api/v1
|
||||
FORGE_REPO: Transaction-Science/open-standards
|
||||
MATURIN_VERSION: 1.15.0
|
||||
ZIG_VERSION: 0.16.0
|
||||
|
||||
jobs:
|
||||
version:
|
||||
name: the tag is the command line's version
|
||||
runs-on: linux
|
||||
outputs:
|
||||
version: ${{ steps.v.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- id: v
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
v="${GITHUB_REF_NAME#wai-quantum-cli-v}"
|
||||
crate="$(sed -n 's/^version = "\(.*\)"$/\1/p' wai/wai-quantum-cli/Cargo.toml | head -1)"
|
||||
[ "$v" = "$crate" ] || { echo "::error::the tag says $v, wai-quantum-cli/Cargo.toml says $crate"; exit 1; }
|
||||
echo "the Python package: $(sed -n 's/^version = "\(.*\)"$/\1/p' wai/wai-quantum-py/Cargo.toml | head -1)"
|
||||
echo "version=$v" >> "$GITHUB_OUTPUT"
|
||||
|
||||
macos:
|
||||
name: macOS · ${{ matrix.triple }}
|
||||
needs: version
|
||||
runs-on: macos
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
triple: [aarch64-apple-darwin, x86_64-apple-darwin]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
# launchd's PATH omits cargo and uv on the macOS host runner.
|
||||
- name: Put cargo and uv on PATH
|
||||
shell: bash
|
||||
run: |
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
- name: Build, check and hash
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
t="${{ matrix.triple }}"
|
||||
rustup target add "$t"
|
||||
tools="$RUNNER_TEMP/tools"; dist="$RUNNER_TEMP/dist"; rm -rf "$tools" "$dist"
|
||||
uv venv -q --python 3.12 "$tools"
|
||||
uv pip install -q --python "$tools/bin/python" "maturin==$MATURIN_VERSION"
|
||||
(cd wai/wai-quantum-py && nice -n 10 "$tools/bin/maturin" build --release --locked --target "$t" -o "$dist")
|
||||
whl="$(ls "$dist"/wai_quantum-*.whl)"
|
||||
if [ "$t" = "$(rustc -vV | sed -n 's/^host: //p')" ]; then
|
||||
py="$RUNNER_TEMP/py39"; rm -rf "$py"
|
||||
uv venv -q --python 3.9 "$py"
|
||||
uv pip install -q --python "$py/bin/python" --no-deps "$whl"
|
||||
(cd "$RUNNER_TEMP" && "$py/bin/python" -I "$GITHUB_WORKSPACE/wai/wai-quantum-py/tests/smoke.py")
|
||||
fi
|
||||
(cd "$dist" && for f in *.whl; do shasum -a 256 "$f" > "$f.sha256"; done; ls -l)
|
||||
- name: Attach to the release
|
||||
shell: bash
|
||||
env:
|
||||
FORGE_TOKEN: ${{ github.token }}
|
||||
run: bash wai/wai-quantum-cli/release/publish.sh "$GITHUB_REF_NAME" "wai-quantum ${{ needs.version.outputs.version }}" "$RUNNER_TEMP"/dist/*
|
||||
|
||||
linux:
|
||||
name: Linux · ${{ matrix.triple }}
|
||||
needs: version
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: linux
|
||||
triple: x86_64-unknown-linux-gnu
|
||||
- runner: linux-arm64
|
||||
triple: aarch64-unknown-linux-gnu
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Rust 1.98.0 and uv
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH="$HOME/.local/bin:$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 "${{ matrix.triple }}"
|
||||
command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
- name: Build (manylinux2014, with zig), check and hash
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
t="${{ matrix.triple }}"
|
||||
tools="$RUNNER_TEMP/tools"; dist="$RUNNER_TEMP/dist"; rm -rf "$tools" "$dist"
|
||||
uv venv -q --python 3.12 "$tools"
|
||||
uv pip install -q --python "$tools/bin/python" "maturin==$MATURIN_VERSION" "ziglang==$ZIG_VERSION"
|
||||
export PATH="$tools/bin:$PATH"
|
||||
(cd wai/wai-quantum-py && maturin build --release --locked --zig --compatibility manylinux2014 --target "$t" -o "$dist")
|
||||
whl="$(ls "$dist"/wai_quantum-*.whl)"
|
||||
case "$whl" in *manylinux2014*) ;; *) echo "::error::not a manylinux2014 wheel: $whl"; exit 1 ;; esac
|
||||
py="$RUNNER_TEMP/py39"; rm -rf "$py"
|
||||
uv venv -q --python 3.9 "$py"
|
||||
uv pip install -q --python "$py/bin/python" --no-deps "$whl"
|
||||
(cd "$RUNNER_TEMP" && "$py/bin/python" -I "$GITHUB_WORKSPACE/wai/wai-quantum-py/tests/smoke.py")
|
||||
(cd "$dist" && for f in *.whl; do sha256sum "$f" > "$f.sha256"; done; ls -l)
|
||||
- name: Attach to the release
|
||||
shell: bash
|
||||
env:
|
||||
FORGE_TOKEN: ${{ github.token }}
|
||||
run: bash wai/wai-quantum-cli/release/publish.sh "$GITHUB_REF_NAME" "wai-quantum ${{ needs.version.outputs.version }}" "$RUNNER_TEMP"/dist/*
|
||||
|
||||
windows:
|
||||
name: Windows · x86_64-pc-windows-msvc
|
||||
needs: version
|
||||
runs-on: windows
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CI: ""
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Build, check and hash
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Remove-Item Env:CI -ErrorAction SilentlyContinue
|
||||
if (-not (Get-Command uv -ErrorAction SilentlyContinue)) {
|
||||
powershell -ExecutionPolicy Bypass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
||||
$env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
|
||||
}
|
||||
$tools = Join-Path $env:RUNNER_TEMP 'tools'
|
||||
$dist = Join-Path $env:RUNNER_TEMP 'dist'
|
||||
$py39 = Join-Path $env:RUNNER_TEMP 'py39'
|
||||
Remove-Item $tools, $dist, $py39 -Recurse -Force -ErrorAction Ignore
|
||||
uv venv -q --python 3.12 $tools
|
||||
if ($LASTEXITCODE -ne 0) { throw "no venv for the build tools" }
|
||||
uv pip install -q --python "$tools\Scripts\python.exe" "maturin==$env:MATURIN_VERSION"
|
||||
if ($LASTEXITCODE -ne 0) { throw "maturin did not install" }
|
||||
Push-Location wai\wai-quantum-py
|
||||
& "$tools\Scripts\maturin.exe" build --release --locked --target x86_64-pc-windows-msvc -o $dist
|
||||
if ($LASTEXITCODE -ne 0) { throw "the wheel did not build" }
|
||||
Pop-Location
|
||||
$whl = (Get-ChildItem $dist -Filter 'wai_quantum-*.whl').FullName
|
||||
uv venv -q --python 3.9 $py39
|
||||
uv pip install -q --python "$py39\Scripts\python.exe" --no-deps $whl
|
||||
if ($LASTEXITCODE -ne 0) { throw "the wheel did not install" }
|
||||
Push-Location $env:RUNNER_TEMP
|
||||
& "$py39\Scripts\python.exe" -I (Join-Path $env:GITHUB_WORKSPACE 'wai\wai-quantum-py\tests\smoke.py')
|
||||
if ($LASTEXITCODE -ne 0) { throw "the smoke checks failed" }
|
||||
Pop-Location
|
||||
foreach ($f in Get-ChildItem $dist -Filter '*.whl') {
|
||||
$h = (Get-FileHash $f.FullName -Algorithm SHA256).Hash.ToLower()
|
||||
Set-Content -NoNewline -Path "$($f.FullName).sha256" -Value "$h $($f.Name)`n"
|
||||
}
|
||||
- name: Attach to the release
|
||||
shell: pwsh
|
||||
env:
|
||||
FORGE_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$H = @{ Authorization = "token $env:FORGE_TOKEN" }
|
||||
$base = "$env:FORGE_API/repos/$env:FORGE_REPO/releases"
|
||||
$tag = $env:GITHUB_REF_NAME
|
||||
$rel = $null
|
||||
for ($i = 0; $i -lt 6 -and -not $rel; $i++) {
|
||||
try { $rel = Invoke-RestMethod -Headers $H -Uri "$base/tags/$tag" } catch {
|
||||
try { Invoke-RestMethod -Headers $H -Method Post -Uri $base -ContentType 'application/json' -Body (@{ tag_name = $tag; name = "wai-quantum ${{ needs.version.outputs.version }}" } | ConvertTo-Json) | Out-Null } catch {}
|
||||
Start-Sleep -Seconds 3
|
||||
}
|
||||
}
|
||||
if (-not $rel) { throw "no release for $tag" }
|
||||
foreach ($f in Get-ChildItem (Join-Path $env:RUNNER_TEMP 'dist')) {
|
||||
foreach ($a in (Invoke-RestMethod -Headers $H -Uri "$base/$($rel.id)/assets" | Where-Object { $_.name -eq $f.Name })) {
|
||||
Invoke-RestMethod -Headers $H -Method Delete -Uri "$base/$($rel.id)/assets/$($a.id)" | Out-Null
|
||||
}
|
||||
curl.exe -fsS -H "Authorization: token $env:FORGE_TOKEN" -X POST "$base/$($rel.id)/assets?name=$($f.Name)" -F "attachment=@$($f.FullName);type=application/octet-stream" -o NUL -w "uploaded $($f.Name): http %{http_code}`n"
|
||||
if ($LASTEXITCODE -ne 0) { throw "the upload of $($f.Name) failed" }
|
||||
}
|
||||
100
.github/workflows/wai-quantum-py.yml
vendored
Normal file
100
.github/workflows/wai-quantum-py.yml
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
name: wai-quantum for Python
|
||||
|
||||
# The Python package (wai/wai-quantum-py): the shared job engine as a pyo3 extension
|
||||
# module (abi3, Python 3.9 on), the service client and the notebook widgets. On
|
||||
# Linux and on macOS, ci/check.sh builds the command line and the job service from
|
||||
# this checkout, clippy on the module, the wheel with maturin, installs the wheel
|
||||
# in a fresh venv with the pinned and hashed test requirements, runs pytest with
|
||||
# every test required (a job run in Python equals the command line's and the
|
||||
# service's; receipts verify across them; the widgets' front ends run under node),
|
||||
# executes the doc notebooks against a job service started here and holds each to
|
||||
# its stored outputs, and installs the same wheel alone on Python 3.9.
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-py/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-service/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-py.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-py/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-service/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-py.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-py.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches the Python package: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
py-linux:
|
||||
name: python · linux
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: linux
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Rust 1.98.0 with clippy, and uv
|
||||
shell: bash
|
||||
run: |
|
||||
export PATH="$HOME/.local/bin:$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 --component clippy
|
||||
rustup default 1.98.0
|
||||
command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
command -v node >/dev/null 2>&1 || { echo "::error::no node on this runner: the widgets' front ends are tested with it"; exit 1; }
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
- name: Build, test and run the notebooks
|
||||
shell: bash
|
||||
run: bash wai/wai-quantum-py/ci/check.sh
|
||||
|
||||
py-macos:
|
||||
name: python · macos
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: macos
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
# launchd's PATH omits cargo, uv and node on the macOS host runner.
|
||||
- name: Put cargo, uv and node on PATH
|
||||
shell: bash
|
||||
run: |
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
||||
echo "/opt/homebrew/bin" >> "$GITHUB_PATH"
|
||||
- name: Build, test and run the notebooks
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
nice -n 10 bash wai/wai-quantum-py/ci/check.sh
|
||||
48
.github/workflows/wai-quantum-qpu.yml
vendored
48
.github/workflows/wai-quantum-qpu.yml
vendored
|
|
@ -5,7 +5,14 @@ name: wai-quantum-qpu
|
|||
# in the provider's format, runs it on wai-quantum's simulator, and answers in
|
||||
# the provider's result shape and bit order), certification through the
|
||||
# fabric, the probe that catches a service with another bit order, and curl
|
||||
# end to end against a local server. No request leaves the runner.
|
||||
# end to end against a local server. And the person's own providers: the
|
||||
# open provider protocol against the reference provider over both
|
||||
# transports (a local process and HTTP through curl), its conformance
|
||||
# vectors, the reference's pinned counts, the registry with its credential
|
||||
# in a file only its owner reads, the refusal of a run that is not free
|
||||
# until it is confirmed, receipts that verify, and no credential in
|
||||
# anything a run returns; and, on macOS, the keychain in a keychain file
|
||||
# made for the test. No request leaves the runner, and nothing spends money.
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
|
@ -68,10 +75,45 @@ jobs:
|
|||
run: |
|
||||
set -euo pipefail
|
||||
command -v curl >/dev/null || { echo "::error::no curl: the transport test would pass over nothing"; exit 1; }
|
||||
# The credentials go to files here: CI has no keychain, and the
|
||||
# tests never touch one but the macOS leg's own.
|
||||
export WAI_QUANTUM_CREDENTIALS=file
|
||||
cargo test --locked 2>&1 | tee "$RUNNER_TEMP/test.log"
|
||||
grep -qE '^test result: ok\. 8 passed; 0 failed' "$RUNNER_TEMP/test.log" || { echo "::error::not every client test ran and passed"; exit 1; }
|
||||
grep -q '^test curl_carries_a_request_to_a_server_and_back \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the transport test did not run"; exit 1; }
|
||||
# The library (34), the clients against their contracts (8), and the
|
||||
# providers end to end (12), each binary's count pinned.
|
||||
for n in 34 8 12; do
|
||||
grep -qE "^test result: ok\. $n passed; 0 failed" "$RUNNER_TEMP/test.log" || { echo "::error::a test binary did not pass all $n of its tests"; exit 1; }
|
||||
done
|
||||
for t in curl_carries_a_request_to_a_server_and_back every_operation_over_http every_operation_over_a_local_process \
|
||||
the_reference_conforms_over_both_transports the_reference_gives_its_pinned_counts_on_every_platform \
|
||||
a_run_that_is_not_free_is_refused_until_confirmed_and_carries_its_cost \
|
||||
a_credential_reaches_the_provider_and_nothing_a_run_returns; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/test.log" || { echo "::error::$t did not run and pass"; exit 1; }
|
||||
done
|
||||
- name: Clippy
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-qpu
|
||||
run: cargo clippy --locked --all-targets --no-deps -- -D warnings
|
||||
|
||||
keychain:
|
||||
name: credentials in the keychain (macos)
|
||||
needs: relevant
|
||||
if: needs.relevant.outputs.run == 'true'
|
||||
runs-on: macos
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Put cargo on PATH
|
||||
shell: bash
|
||||
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
# The registry's tests, the keychain's among them: a credential kept,
|
||||
# read back, replaced and forgotten through the system tool, in a
|
||||
# keychain file the test makes and deletes (the runner's own keychain
|
||||
# is never touched).
|
||||
- name: The keychain test
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum-qpu
|
||||
run: |
|
||||
set -euo pipefail
|
||||
nice -n 10 cargo test --locked --lib registry:: 2>&1 | tee "$RUNNER_TEMP/keychain.log"
|
||||
grep -q '^test registry::tests::the_macos_keychain_keeps_reads_and_forgets_a_credential \.\.\. ok$' "$RUNNER_TEMP/keychain.log" || { echo "::error::the keychain test did not run and pass"; exit 1; }
|
||||
|
|
|
|||
11
.github/workflows/wai-quantum-studio.yml
vendored
11
.github/workflows/wai-quantum-studio.yml
vendored
|
|
@ -6,7 +6,11 @@ name: wai-quantum studio and desktop
|
|||
# quantum_engine) and run in a browser by test/studio.test.mjs: linted, drawn and
|
||||
# planned as it is typed, run here with its receipt checked here, an error marked
|
||||
# on its line, any angle on the state vector, Ctrl+Enter, and the program and the
|
||||
# history kept across a reload; nothing scrolls sideways at a phone's width;
|
||||
# history kept across a reload; a device target's coupling map coloured by its
|
||||
# errors, a run placed and simulated on it, and the layout drawn on the map;
|
||||
# nothing scrolls sideways at a phone's width;
|
||||
# - test/hardware.test.mjs, without a browser: "Your hardware" asks the person before
|
||||
# a run that is not free, never before a free one, and sends nothing on a "no";
|
||||
# - the desktop app's tests and clippy with warnings as errors, and `check`: a job
|
||||
# run in the app's worker process, sealed in the app with a key that never leaves
|
||||
# it, and verified, with no window.
|
||||
|
|
@ -23,6 +27,7 @@ on:
|
|||
- 'wai/wai-quantum-desktop/**'
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-qpu/**'
|
||||
- 'wai/wai-web/**'
|
||||
- 'wai/wai-rs/**'
|
||||
- 'rust-toolchain.toml'
|
||||
|
|
@ -33,6 +38,7 @@ on:
|
|||
- 'wai/wai-quantum-desktop/**'
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/wai-quantum-cli/**'
|
||||
- 'wai/wai-quantum-qpu/**'
|
||||
- 'wai/wai-web/**'
|
||||
- 'wai/wai-rs/**'
|
||||
- 'rust-toolchain.toml'
|
||||
|
|
@ -100,6 +106,7 @@ jobs:
|
|||
set -euo pipefail
|
||||
npm ci --no-audit --no-fund
|
||||
npx playwright install --with-deps chromium
|
||||
node test/hardware.test.mjs
|
||||
node build.mjs --pkg "$RUNNER_TEMP/pkg"
|
||||
node test/studio.test.mjs
|
||||
|
||||
|
|
@ -132,6 +139,8 @@ jobs:
|
|||
set -euo pipefail
|
||||
nice -n 10 cargo test --locked --release 2>&1 | tee "$RUNNER_TEMP/test.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/test.log" || { echo "::error::no test ran"; exit 1; }
|
||||
grep -q '^test tests::a_run_on_a_provider_is_estimated_refused_until_confirmed_and_sealed_with_the_app_s_key \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the provider run test did not run and pass"; exit 1; }
|
||||
grep -q '^test tests::device_targets_are_listed_shown_and_placed_for_the_page \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the device targets 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
|
||||
|
|
|
|||
153
.github/workflows/wai-quantum-verdict.yml
vendored
Normal file
153
.github/workflows/wai-quantum-verdict.yml
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
name: wai-quantum verdicts and repairs
|
||||
|
||||
# The verified-answer contract (wai/wai-quantum/src/engine/verdict.rs,
|
||||
# repair.rs and refusal.rs): a verdict's level for every answer, each intent
|
||||
# checked against ground truth, a repair held to the flagged lines, the job
|
||||
# layer's refusal codes and the page that documents them, and the byte
|
||||
# identity of every job that asks for no verdict. Then the intent
|
||||
# conformance set (wai/quantum-conformance/intents/: programs, their intents
|
||||
# and the verdict each must get), 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. The browser build runs the
|
||||
# set too (wai-web-wasm.yml, wai-web's wasm32 tests).
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/quantum-conformance/intents/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-verdict.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'wai/wai-quantum/**'
|
||||
- 'wai/quantum-conformance/intents/**'
|
||||
- 'rust-toolchain.toml'
|
||||
- '.github/workflows/wai-quantum-verdict.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-verdict.yml \
|
||||
"${{ github.event.pull_request.base.sha }}" \
|
||||
"${{ github.event.pull_request.head.sha }}")
|
||||
echo "this change touches the verdicts: $r"
|
||||
echo "run=$r" >> "$GITHUB_OUTPUT"
|
||||
|
||||
native:
|
||||
name: verdicts, repairs and the intent 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 verdict, the repair and the codes
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --lib -- engine::verdict:: engine::repair:: engine::refusal:: engine::job:: 2>&1 | tee "$RUNNER_TEMP/verdict.log"
|
||||
grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/verdict.log" || { echo "::error::the verdict's tests did not pass"; exit 1; }
|
||||
for t in engine::verdict::tests::each_intent_is_decided_as_ground_truth_says \
|
||||
engine::verdict::tests::the_level_is_the_weakest_check_and_holds_says_the_outcome \
|
||||
engine::repair::tests::each_rule_makes_the_fix_a_person_would_on_the_flagged_line \
|
||||
engine::repair::tests::a_proposal_may_change_only_the_flagged_lines \
|
||||
engine::refusal::tests::the_documented_table_is_the_table \
|
||||
engine::job::tests::a_job_that_asks_for_no_verdict_gives_the_bytes_it_gave \
|
||||
engine::job::tests::every_refusal_an_agent_can_act_on_carries_its_code; do
|
||||
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/verdict.log" || { echo "::error::$t did not run"; exit 1; }
|
||||
done
|
||||
- name: The intent conformance set
|
||||
shell: bash
|
||||
working-directory: wai/wai-quantum
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo test --locked --release --features full --test intent_conformance 2>&1 | tee "$RUNNER_TEMP/intents.log"
|
||||
grep -q 'test result: ok. 2 passed; 0 failed' "$RUNNER_TEMP/intents.log" || { echo "::error::the intent set did not pass"; exit 1; }
|
||||
|
||||
wasip2:
|
||||
name: the intent set and the verdict 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 intent 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 intent_conformance 2>&1 | tee "$RUNNER_TEMP/wasip2.log"
|
||||
grep -q 'test result: ok. 1 passed; 0 failed' "$RUNNER_TEMP/wasip2.log" || { echo "::error::the intent set did not pass under wasip2"; exit 1; }
|
||||
- name: The verdict and the repair 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 --lib -- engine::verdict:: engine::repair:: engine::refusal:: 2>&1 | tee "$RUNNER_TEMP/wasip2-lib.log"
|
||||
for m in engine::verdict engine::repair engine::refusal; do
|
||||
grep -q "^test $m::.* \.\.\. ok$" "$RUNNER_TEMP/wasip2-lib.log" || { echo "::error::no test of $m ran"; exit 1; }
|
||||
done
|
||||
27
.github/workflows/wai-web-wasm.yml
vendored
27
.github/workflows/wai-web-wasm.yml
vendored
|
|
@ -166,9 +166,16 @@ jobs:
|
|||
# quantum_engine, which only the IDE's bundle carries): a job planned, run and
|
||||
# signed in wasm32 under Node, its receipt checked there and a changed result
|
||||
# refused, every method a tab holds run with no clock and no threads, a
|
||||
# program's critique, equivalence check and variants, and its classical
|
||||
# shortcuts with a contraction search. The count is the four tests above and
|
||||
# its four.
|
||||
# program's critique, equivalence check and variants, its classical
|
||||
# shortcuts with a contraction search, the OpenQASM 3 conformance corpus
|
||||
# (wai/quantum-conformance/qasm3/bundle.json) read and run in the page, a
|
||||
# compile to Clifford+T and a resource estimate whose sealed bytes match the
|
||||
# native build's pinned digests, the debugger's branches and a position
|
||||
# asked twice giving the same bits, a job on a device target, the intent
|
||||
# conformance set (wai/quantum-conformance/intents/bundle.json) run in the
|
||||
# page to the verdicts its manifest gives and each worked out again by
|
||||
# engine_verdict, and a repair there. The count is the four tests above
|
||||
# and its eleven.
|
||||
- name: The job engine in a page (wasm32 tests under Node)
|
||||
shell: bash
|
||||
working-directory: wai/wai-web
|
||||
|
|
@ -176,22 +183,28 @@ 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. 8 passed; 0 failed" "$RUNNER_TEMP/wai-web-engine-wasm.log"
|
||||
grep -q "test result: ok. 15 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
|
||||
# workbench run and sealed in the page, a program's history recorded and
|
||||
# blamed there, the reader's rules checking a proposal, what is new in a
|
||||
# program and in a workbench entry, the reader's taste learned there, the
|
||||
# rewrites offered and explained there, convergence measured there, and a
|
||||
# study run there.
|
||||
# rewrites offered and explained there, convergence measured there, a
|
||||
# study run there, the reader's diagnostic codes and its whole language (a
|
||||
# subroutine, an inverse, a power) answered there, a compile sealed there
|
||||
# that runs bit-exact, an estimate sealed there and re-run, the debugger's
|
||||
# steps and branches there, a drawing's edits and its SVG, LaTeX and words
|
||||
# there, device targets listed, shown, placed and run there, a verdict
|
||||
# sealed there and worked out again, and a repair held to the flagged
|
||||
# lines there.
|
||||
- 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. 14 passed; 0 failed" "$RUNNER_TEMP/wai-web-engine.log"
|
||||
grep -q "test result: ok. 22 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
|
||||
|
|
|
|||
|
|
@ -3474,7 +3474,7 @@ version = "0.1.0"
|
|||
|
||||
[[package]]
|
||||
name = "wai-quantum"
|
||||
version = "0.6.16"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"ed25519-dalek",
|
||||
|
|
|
|||
210
wai/CHANGELOG.md
210
wai/CHANGELOG.md
|
|
@ -2626,6 +2626,216 @@ wire format may change and such changes are recorded here.
|
|||
- **`tools/ops-gpu-bench`** times each capability's decode with its graphs on the CPU and on each adapter, and reads the energy counters the host has.
|
||||
- **CI:** `wai-ops-gpu.yml` runs the Metal and browser legs on the `macos` runner, and requires on a runner with no GPU that the device tests skip without `WAI_OPS_GPU_REQUIRE` and fail with it.
|
||||
|
||||
### wai-quantum 0.7.0 and wai-quantum-cli 0.2.0: one OpenQASM 3 reader, synthesis, verdicts and repair, estimates, device targets, the debugger, and a version contract
|
||||
|
||||
This release carries the twelve entries below it, down to the study of the co-design, to the package registry. `wai-quantum-cli` 0.2.0 requires `wai-quantum` 0.7.0 and `wai-quantum-qpu` 0.3.0, which requires 0.7.0 too; the job service is 0.2.0. The Python package stays 0.1.0 and the editor extension keeps its version. What each version now promises is the policy, `wai-quantum/VERSIONING.md`; nothing is deprecated.
|
||||
|
||||
- **wai-quantum 0.7.0:**
|
||||
- one OpenQASM 3 reader for every surface (`qasm::read`), every refusal and warning under a stable code (`qasm::diag`, the `Q` codes), and the job layer's refusals under theirs (`engine::refusal`, the `J` codes);
|
||||
- synthesis and certified compilation (`engine::synth`, `engine::compile`): every pass checked where it acts and one certificate per compile, to the basis `clifford_t` within a stated `ε` or `standard`; a job may ask to be compiled first;
|
||||
- a verdict for every answer about a program (`engine::verdict`): the level the engine checked to, from refused to proof, intents checked by proof or by evidence, and repairs held to the flagged lines (`engine::repair`);
|
||||
- resource estimation from programs (`engine::estimate`), each estimate sealed in the resource-estimate receipt family;
|
||||
- device targets (`engine::targets`): a device's calibration snapshot read into one document, `wai.quantum.target/1`, its noise derived, a program placed where it is most likely to succeed, and the target's hash in the receipt;
|
||||
- a debugger with branch enumeration and exact weights, and statistical tests (`engine::debug`, `engine::stats`);
|
||||
- the editors' language service and formatter (`engine::editor`), the agent front door's guide (`engine::guide`), a job on the person's own provider (`engine::provider`), and the study (`engine::study`);
|
||||
- versioned JSON Schemas for every document it writes (`engine::schema`), each result naming the engine that made it and its schema inside what its receipt seals.
|
||||
- **wai-quantum-cli 0.2.0:** `new`, `test`, `setup-agent`, `mcp config | install`, `docs`, `lsp`, `fmt`, `dap`, `diagnostics`, `compile`, `repair`, `estimate`, `debug`, `targets`, `providers`, `run --intent | --compile | --repair | --target | --provider` and `version`; the MCP tools `repair_qasm`, `compile_qasm`, `qasm_diagnostics`, `estimate_resources`, `debug_step`, `debug_branches`, `list_targets`, `show_target`, `run_on_target`, `providers_list`, `provider_estimate` and `run_on_provider`, every tool with its output schema and every answer about a program with its verdict.
|
||||
- **wai-quantum-qpu 0.3.0:** the open provider protocol (`wai.quantum.provider/1`), its reference provider and conformance checker, and a registry whose credentials stay in the keychain.
|
||||
- **What changed that a caller may have to change** (`cargo-semver-checks` against 0.6.16 and 0.2.0): `engine::catalog::Request` gained `diagnostics`, `compiled` and `repaired`, `engine::catalog::Plan` gained `target`, and `qasm::Program` gained `extra`: take them from `catalog::read`, `catalog::plan` and `qasm::read` rather than writing them out. `quantum_resource_receipt::Program` gained the variant `Counted`: a `match` on it needs that arm. In `wai-quantum-qpu`, `JobInfo` and `JobRecord` gained `calibration` and `charged`. Every result now names its engine and schema, so a stored result's bytes and its receipt's digest differ from 0.6.16's for the same request; a receipt 0.6.16 issued still verifies.
|
||||
- Every lockfile that holds one of these crates moves with them (sixteen), so a `--locked` build still reads its own.
|
||||
|
||||
### wai-quantum: the version and deprecation contract, schemas as data, and versions in what is written
|
||||
|
||||
Anyone building on WAI Quantum can read what is stable and for how long, and is told by the tools before anything they use changes.
|
||||
|
||||
- **The policy** ([`wai-quantum/VERSIONING.md`](wai-quantum/VERSIONING.md)), linked from every WAI Quantum README: the public surface (the engine's documented API, the command line's verbs, flags, exit statuses and `--json`, the job JSON, both MCP servers' tools and schemas, the receipt, the job service's API, the Python package, the provider protocol, the editor extension's settings, the grammar's node names), what each part of a version number promises, the support windows the owner decided on 2026-10-27 (at least a year between majors, six months of fixes for the previous major, deprecation at least one minor release before removal), how a deprecated item says so on each surface, and the rule before 1.0 (the first non-zero component is the major; the windows begin at 1.0). [`DEPRECATIONS.md`](wai-quantum/DEPRECATIONS.md) lists each deprecated item with its replacement; none today.
|
||||
- **Schemas as data:** versioned JSON Schemas (2020-12), `wai.quantum.<document>/<major>` kept as `<document>.v<major>.json`: the job request, the job result, the job, the receipt (its second form; the first still verifies), the plan, a compile with its certificate, the engine's tools' answers (the reader's diagnostic codes among them), the versions a host reports (`wai-quantum/schemas/`); the local MCP server's own tools' answers (`wai-quantum-cli/schemas/`), the job service's (`wai-quantum-service/schemas/`), and the provider protocol's messages (`wai-quantum-qpu/schemas/`). `engine::schema` checks a document against them; the tests also refuse a member a schema does not name, so a change to what the code writes fails until its schema changes with it.
|
||||
- **Every MCP tool says what it answers:** each tool of both servers carries its answer's schema as its `outputSchema`, standing alone. A test calls every tool and holds its answer to it. The local server's tool list is committed (`wai-quantum-cli/docs/local-mcp.json`) beside the service's, both held to the live lists.
|
||||
- **Versions in what is written:** every result names the engine that made it and the schema it follows (`"engine": {"name": "wai-quantum", "version": …}`, `"schema": "wai.quantum.job-result/1"`), inside what its receipt seals. The receipt's form did not change; the canonical text of a new result holds two more members. Two job bodies sealed by the engine as it was before (a run here and a run on a provider) are kept with their digests pinned, and still verify.
|
||||
- **Versions reported:** `wai-quantum version [--json]`; both MCP servers in `initialize` under `_meta["science.transaction.wai/versions"]`; the job service in `GET /v1` and `quantum_service_info`. The agent docs (llms.txt, llms-full.txt, the `AGENTS.md` block, the Agent Skill) say how to read them and where the policy is.
|
||||
- **CI:** `wai-quantum-contract.yml` on Linux: `cargo-semver-checks` 0.51.0 against wai-quantum 0.6.16 and wai-quantum-cli 0.1.4 (it lists every breaking change, and fails only on one made without a major bump), the schema tests by name, the policy linked from every README, and the deprecations page's table.
|
||||
### wai-quantum: a verdict for every answer, stable refusal codes, and repairs held to the flagged lines
|
||||
|
||||
Every answer an agent or a person gets about a program states one verification level, so "valid" is never the claim (`wai-quantum/docs/verdicts.md`).
|
||||
|
||||
- **The verdict** (`engine::verdict`): the level of an ordered ladder (`refused` < `parsed` < `executed` < `evidence` < `proof`), whether the intents hold, and the level in one plain line; with what the reader said (its codes), the method and its accuracy class, each intent's check, the critique's findings and the repairs made.
|
||||
- Intents: an exact distribution with its total variation distance (the state vector, or under noise the density matrix), the same circuit as a reference by the equivalence ladder (proof or evidence), the same state from |0…0⟩, or samples of the run held to a stated distribution by a stated test at a stated level (the debugger's `sampled` intent, now in the engine for every surface: evidence, never proof). `"require": "proof"` counts evidence as unchecked.
|
||||
- A run on a device target states its verdict too: its intents checked on the program, a sampled intent on samples of the target's run.
|
||||
- A job asks with `"intent"` or `"verdict": true`, and its result carries the verdict, sealed by the receipt; the plan admits the check's memory. A job that asks for neither gives the bytes it gave before (pinned against the engine before this change).
|
||||
- The checker `wai-quantum test` used moved into the engine, and `test` now runs the program with its intents; `--junit` reads the engine's verdict.
|
||||
- **Stable refusal codes for what is asked of a program** (`engine::refusal`, `docs/job-refusals.md`): the request (`J001`–`J006`), the method (`J010`–`J012`), intents and repairs (`J020`–`J022`) and the host (`J030`–`J032`), each refused or retry, beside the reader's `Q` codes. A refusal ends with its code, a reader's cause before it (`[Q500] [J011]`); the service's HTTP refusals carry it as `code`.
|
||||
- **Repairs** (`engine::repair`): the fixes that are mechanical, each on the lines its diagnostic flags (a missing `;`, an undeclared register's size, a measurement with no target, an unbounded `while` given its bound, a non-dyadic angle rounded to the bits chosen with its rounding stated); a proposal that changes any other line rejected (`J021`); what needs a person returned with the reader's advice. A job may ask to be repaired first.
|
||||
- **Surfaces**:
|
||||
- the command line: `run --intent FILE` (a reference program, a distribution, intents, or `intent.json`), `--verdict`, `--repair`, and `repair FILE` (`--proposed`, `--max-iterations`, `--dyadic-bits`, `--size`);
|
||||
- both MCP servers: `intent` and `repair` on `run_quantum_circuit`, which always states its verdict; the tool `repair_qasm`; the verdict in every answer about a program and the codes in every refusal; versioned output schemas on every tool; the resource `wai-quantum://docs/verdicts`; the rules and prompts point agents at the verdict and `repair_qasm`, and the generated agent docs and the Agent Skill say so;
|
||||
- the service: intents and repairs in jobs, held to the equivalence bound; `POST /v1/repair`;
|
||||
- the Studio and the desktop app: a badge with the level on every run and every assistant proposal;
|
||||
- the browser engine: `engine_verdict` and `engine_repair`;
|
||||
- Python: `run(..., intent=...)`, `Job.verdict`, `wai_quantum.verdict` and `wai_quantum.repair`.
|
||||
- **Conformance** (`quantum-conformance/intents/`): programs, their intents and the verdict each must get, every level covered and the distances known by hand, run natively and under `wasm32-wasip2` (`wai-quantum-verdict.yml`) and in the browser build (`wai-web-wasm.yml`).
|
||||
### wai-quantum: resource estimation from programs
|
||||
|
||||
What a fault-tolerant machine would need to run a program, derived from the program itself, calibrated from the crate's own decoders, and sealed (`wai-quantum/docs/estimate.md`).
|
||||
|
||||
- **Logical counts** (`engine::estimate::count`): the program written in Clifford gates, `T`, `z` rotations, Toffolis (one CCZ state each) and measurements:
|
||||
- a gate under several controls goes through clean ancillas, a ladder of Toffolis computed and uncomputed: `x`, `y`, `z` or `h` under `c ≥ 3` controls takes `2c − 3` Toffolis and `c − 2` ancillas, a phase under `c ≥ 2` takes `2c` and `c`;
|
||||
- each rotation synthesised at its own angle within its share of the budget's synthesis share, its `T` count the word's (`engine::synth::rz`);
|
||||
- `T` gates, Toffolis, rotations and the `T` in their words, measurements, non-Clifford, rotation and `T` depth, total depth, and logical qubits with ancillas;
|
||||
- a program that branches is counted step by step, each step once, an upper bound it says it is.
|
||||
- **Ground truth**: a Bell pair, `T` chains in series and in parallel, the ripple-carry adder (`2n` Toffolis), the QFT (`3(n−1)` `T`, `3(n−1)(n−2)/2` rotations); every ladder held to the gate it replaces on dense unitaries with its ancillas at `|0⟩`; each rotation's `T` count equal to the synthesiser's.
|
||||
- **The physical estimate**: the planar model (`quantum_resource`) on those counts, a rotation layer taking as many steps as its longest word has `T` gates; the headline and the frontier of estimates no other beats on both physical qubits and runtime.
|
||||
- **Calibration** (`engine::estimate::calibration`): on gate-based qubits the surface code's `P(d) = a·(p/p*)^((d+1)/2)` is fitted to the memory experiment decoded by exact matching (`a = 0.0233`, `p* = 0.01004`) or by union-find (`a = 0.0214`, `p* = 0.00952`) on the same shots: `d` 3, 5, 7 by `p` 0.002 to 0.005, 100 000 shots (25 000 at `d = 7`), seed 1. The table is in the crate, a release test measures every point again, and the example `estimate_calibration` prints it. The planar model's assumed constants remain available; an extrapolation past the measured range is flagged.
|
||||
- **Receipts**: every estimate a resource-estimate receipt whose job binds the program's digest, every count, the budget, the synthesis share and each rotation's (a new counted-program form; the earlier forms hash as before); the frontier's name the headline's as parent; the answer sealed in a job's form. `engine::estimate::verify` checks the seals and re-runs the request.
|
||||
- **Interchange**: the logical-counts JSON (`numQubits`, `tCount`, `rotationCount`, `rotationDepth`, `cczCount`, `ccixCount`, `measurementCount`) and the routine format (`v1`: routines, ports, resources, children, connections), each read and written, the routine held to its schema, with a self-made fixture. A document's rotations cost the most `T` any of eight reference angles needs.
|
||||
- **Refusals** carry codes `QE02` to `QE08`, beside the reader's own.
|
||||
- **Surfaces**:
|
||||
- the command line: `wai-quantum estimate prog.qasm` (`--budget`, `--qubit NAME|all|FILE`, `--calibration`, `--max-slowdown`, `--counts`, `--routine`, `--export`, `--json`), and `verify` re-running an estimate; `lab estimate` unchanged;
|
||||
- the service: `POST /v1/estimate`, within bounds (200 000 gates, 256 distinct angles, `1e-12` a rotation), and `POST /v1/verify` re-running an estimate;
|
||||
- the MCP tool `estimate_resources` on both servers, with one description and schema, and the verify tools re-running an estimate;
|
||||
- `QuantumEngine.estimate` and `engine_estimate_verify` in a page; `estimate` in the desktop app;
|
||||
- the Studio's Estimate pane: the counts, the estimate, the frontier plotted on log scales and listed, the seals verified and the request re-run in the page;
|
||||
- Python: `wai_quantum.estimate` and `verify_estimate`.
|
||||
- **Determinism**: CI compares an estimate natively and as a WASI component byte for byte, and the browser build's tests estimate one request to the native build's pinned digest. The estimate's tests run under `wasm32-wasip2`, and `wai-quantum-estimate.yml` runs them in release with the whole calibration.
|
||||
|
||||
### wai-quantum: device targets and calibrated noise
|
||||
|
||||
The engine knows real devices: their qubits, pairs, native gates, durations and errors. A program is compiled, laid out and simulated as it would run on one.
|
||||
|
||||
- **The model** (`engine::targets`): each qubit's T1, T2, frequency, readout assignment errors and measurement time; each native gate where it runs, with its error and duration; the coupling map; and the calibration snapshot's id and time. It is one strictly read document, `wai.quantum.target/1`, with a JSON Schema, and the BLAKE3 hash of its RFC 8785 text names the snapshot in a receipt.
|
||||
- **Importers:** the per-qubit and per-gate calibration properties a superconducting-device service publishes (alone or beside its configuration, the form published snapshot devices ship in), an instruction-properties target, the device-capabilities document a cloud service returns, and the open provider protocol's `describe`. Four built-in targets, all synthetic, one in each shape: a 5-qubit line, an 8-qubit ring, a 27-qubit heavy-hexagon lattice and 5 qubits all coupled.
|
||||
- **Noise from a target**, per qubit and per pair. Each gate's reported error becomes the depolarising channel that, with its relaxation, has exactly that average infidelity. T1, T2 and the durations give amplitude damping and dephasing, idling included, and readout comes from the assignment matrix. The density matrix and the branching trajectories take it as a schedule of channels (`quantum_noisy::Schedule`). The global noise model keeps its bits.
|
||||
- **Noise-aware layout and routing:** many layouts and their most reliable routes are compared, and the highest expected success is kept. The compiler's own choice (the fewest swaps) wins unless beaten, and the program is checked against the circuit. `native::compile_at` and weighted routes are new; `native::compile` is unchanged. A provider whose `describe` states its calibration gets its programs placed the same way, in the device's own gates and checked before they are sent, and the receipt says how. The provider protocol now states the `durations` field's form.
|
||||
- **Job JSON:** `target` is a document or a built-in target's name. The plan states the layout, its expected success beside the fewest swaps', and the noise derived. The result carries the same with the target's hash, inside the receipt, and the distance of its distribution from the circuit's ideal one.
|
||||
- **Surfaces:**
|
||||
- the command line: `wai-quantum targets import|list|show|remove|schema` (import also from a provider's describe) and `run --target`/`plan --target`;
|
||||
- MCP on both servers: `list_targets`, `show_target`, `run_on_target`, and `target` in the run tools' schemas, with the agent docs regenerated;
|
||||
- the service: `GET /v1/targets`, `target` in the OpenAPI document, and a worked example (it reads the document given and fetches nothing);
|
||||
- wasm: `engine_targets`, `engine_target` and `engine_target_place`;
|
||||
- the desktop app: the same three, the person's kept targets included;
|
||||
- the Studio: a **Device** section with the coupling map coloured by each pair's and each qubit's error, the chosen layout drawn on it, a snapshot imported, and the result's **Device** block.
|
||||
- **Checked against ground truth:**
|
||||
- a target with no errors gives the ideal distribution to 1e-12 in each of the three gate sets;
|
||||
- T1 decay, T2 coherence and the assignment matrix give their closed forms;
|
||||
- each gate's channels have exactly its reported average infidelity, by its Choi state;
|
||||
- the layout equals an exhaustive search on a line;
|
||||
- a run on a target gives the same bytes natively and under wasmtime (a CI check).
|
||||
- **Not done:** a cross-vendor C device interface is a library with no document form to import; a host that loads one answers the provider protocol's `describe`, which is read. Programs with angles that are not dyadic are refused on a target, since the compile is exact. Crosstalk, leakage, coherent errors and drift are not modelled.
|
||||
|
||||
### wai-quantum: a debugger, statistical tests, state views and editing by the drawing
|
||||
|
||||
What a program does, step by step, with every number the engine's: in the Studio, in editors, from the command line and from agents.
|
||||
|
||||
- **The debugger** (`engine::debug`): a program stepped forward and back one gate, measurement or reset at a time on a method where every number is exact for it: the bit-exact state vector when every angle is a dyadic multiple of 2π, else double precision, and under noise the density matrix beside the noiseless state on the same path.
|
||||
- Breakpoints by line, a measurement's line found through broadcasts, loops and branches.
|
||||
- Probes at any position: the amplitudes with their phases, the probabilities, each qubit's Bloch vector, purity and probability of 1, the reduced density matrix of chosen qubits, and the entanglement across a cut (the entropy of a side of a pure state, or the logarithmic negativity of a small mixed one).
|
||||
- Every branch at the measurements in the middle, with its weight (exact fractions by the stabilizer tableau for a noiseless Clifford program) and the distribution of the final measurements on it; a recorded path replayed, and an outcome the state cannot give refused.
|
||||
- Deterministic: stepping back runs again from a saved state, so a state seen twice is the same bits, and the exact method's state after the last gate is the exact run's, by its `state_hash`. Refused past 16 qubits, or 8 under noise. Its tests are ground truth: teleportation's four branches a quarter each, a Bell pair's reduced states, the noisy steps against the density matrix's run.
|
||||
- **Statistical intents** (`engine::stats`, `wai-quantum test`): `{"sampled": …, "test": "chi_squared" | "g_test", "alpha": …, "shots": …}` runs the program for the stated shots and holds the counts to the distribution by the stated test at the stated level, as evidence; the p-value is the same bits on every platform. `test --junit FILE` writes the verdicts as a JUnit report. The exit codes are as they were.
|
||||
- **The command line:** `wai-quantum debug` prints a position's state or every branch; `wai-quantum dap` serves the debugger over the debug adapter protocol (launch, breakpoints, steps both ways, continue both ways, the probes and the branch tree as variables), driven in `tests/dap.rs` as an editor drives it; `draw --svg`, `--latex` (plain TikZ) and `--describe` (in words).
|
||||
- **Agents:** the stdio MCP server gains `debug_step` and `debug_branches`, read-only and deterministic, and `draw_circuit` takes a `format`; the agent docs are regenerated from the live lists.
|
||||
- **Editors:** the extension contributes breakpoints and a debugger whose launch settings are the adapter's own, held to its source by `test/check.mjs`; the Lua and `languages.toml` configurations register it.
|
||||
- **The Studio:** "Step through", with a slider, the branch tree, each qubit's phase disk with a purity ring and its Bloch sphere in plain SVG, the amplitude and phase table, the reduced state of chosen qubits, and under noise the noisy state against the noiseless one; editing by the drawing (a gate dropped on a wire, dragged or moved and deleted from the keyboard), each an edit the engine makes in the program's text through its syntax tree (`engine::visual`) and recorded as the reader's; the circuit described in the engine's words for a screen reader (`engine::describe`); the drawing saved as SVG or LaTeX (`engine::latex`). The same in the desktop app, natively.
|
||||
- **CI:** the editors workflow runs the debugger's module tests and the adapter's sessions on Linux and macOS; the wasm workflow's counts are now 16 native and 9 under Node.
|
||||
|
||||
### wai-quantum: synthesis and certified compilation
|
||||
|
||||
Circuits synthesised and optimised by the engine, every compile carrying a sealed certificate of how close the output is to the program and how that was established (`wai-quantum/docs/compiler.md`).
|
||||
|
||||
- **Rotation synthesis** (`engine::synth::rz`): `Rz(θ)` as a Clifford+T word within a requested `ε`, by the Ross–Selinger method:
|
||||
- the ε-region and the unit disk as a two-dimensional grid problem over `Z[ω]`, made upright by a grid operator (rotations, shears, `K` and shifts by powers of `1 + √2`), each candidate tested in exact arithmetic;
|
||||
- the norm equation `t†t = ξ` solved prime by prime in `Z[ω]`, or shown to have no solution;
|
||||
- the operator written in its Matsumoto–Amano normal form, the fewest `T` gates of any word for it;
|
||||
- the word multiplied back exactly, and its distance to the rotation recomputed from the word in fixed point and rounded up: that is the distance reported.
|
||||
- `T` counts follow `3·log₂(1/ε)` (99 to 101 at `1e-10`). Against every Clifford+T operator with at most 11 `T` gates, 21 of 24 cases land on the optimum and the rest one above.
|
||||
- **The arithmetic under it**: integers of any size (Knuth division, square roots, a primality test, Pollard–Brent factoring within a step budget), fixed point with 320 fractional bits with `π`, `√2`, sine and cosine, and the rings `Z[√2]`, `Z[ω]` and 2×2 matrices over `D[ω]`. Each held to a ground truth: 128-bit arithmetic, every `t` with small coefficients for the norm equation, brute force for the grid problems.
|
||||
- **One and two qubits**: ZYZ Euler angles of any one-qubit unitary, and the KAK decomposition of any two-qubit unitary into at most three CNOTs (two or none when its canonical coordinates allow), with a deterministic Jacobi eigen-solver.
|
||||
- **Phase folding** (`engine::synth::phase`): phase gates on one parity merged, checked by recomputing the phase polynomial.
|
||||
- **The pass pipeline** (`engine::compile`):
|
||||
- passes `lower`, `simplify`, `phase_fold`, `resynth_1q`, `resynth_2q` and `approximate`, levels 0 to 2, bases (the gate set compiled to) `clifford_t` and `standard`;
|
||||
- each pass checked where it acts, and a pass whose check fails not applied;
|
||||
- one certificate per compile: each pass's counts before and after (gates, CNOTs, `T`, rotations), its check and verdict (`proof`, `exact` or `approximate` with its distance), the `ε` budget, its share per rotation and the bound the distances add to;
|
||||
- up to eight qubits the whole output is also measured against the whole program on dense unitaries;
|
||||
- sealed in a job's form, so the existing receipt check verifies it;
|
||||
- with `"stages": true`, the circuit after each pass as well.
|
||||
- **Compiled jobs**: a job with `"compile": {"epsilon", "level", "basis"}` runs its program compiled first, bit-exact for Clifford+T, and its result's `compiled` states the distance.
|
||||
- **Surfaces**:
|
||||
- the command line: `wai-quantum compile` (`--epsilon`, `--level`, `--basis`, `--json`, `--certificate`) and `run --compile ε`;
|
||||
- the service: `POST /v1/compile`, sealed with the service's key, within bounds (20 000 gates, 256 rotations, `1e-12` a rotation; past them 422 with the local command);
|
||||
- the MCP tool `compile_qasm` on both servers, and `compile` in the job schemas;
|
||||
- `QuantumEngine.compile` in a page, and the desktop app's `compile` command;
|
||||
- the Studio's compile lens: each pass with its counts and check, the certificate verified in the page, and the circuit after any pass drawn.
|
||||
- **Determinism**: CI compiles one program natively and as a WASI component and compares the sealed bytes, and the browser build's tests compile one request to the native build's pinned digest. The synthesis tests also run under `wasm32-wasip2`.
|
||||
|
||||
### wai-quantum: one OpenQASM 3 front end, every refusal and warning under a stable code
|
||||
|
||||
One reader, with the source position of everything it handles, for every surface: the job service, the command line, both MCP servers, the Studio, the desktop app, the edge component and the in-browser IDE.
|
||||
|
||||
- **Diagnostic codes** (`qasm::diag`): every refusal and warning the reader gives, and every construct it lowers, carries or keeps verbatim, has a code with its outcome (refused, lowered, carried, preserved, warned) and a one-line meaning. A diagnostic's text keeps the message people read and ends with its code (`line 3: unknown gate foo [Q103]`); as data it has its line, column and length. The table is `wai-quantum/docs/qasm-diagnostics.md`, which a test holds to the code's table, and is served by `wai-quantum diagnostics [--json]`, the `qasm_diagnostics` tool of both MCP servers and `engine_diagnostic_codes()` in the browser engine. A code never changes meaning once released. `lint` gives the code, the column and the length, and the warnings.
|
||||
- **The language** (`qasm::lex`, `qasm::parse`, `qasm::elab`): `def` subroutines, inlined (classical arguments by value, qubits by reference, values returned, a returned measurement written into the caller's bit, bits of their own fed forward); `inv @`, `pow(k) @` and exact fractional powers, and `ctrl`/`negctrl` on any gate, user gates included, each lowered exactly and held to the matrix it must equal; `float` (16, 32 and 64 bits), `angle[n]` (held to n bits of a turn, so dyadic, with the rounding reported), `complex`, `uint`, `bool`, bit registers set by constants, arrays, casts and the built-in functions, computed with the crate's own functions; `while` (unrolled when its condition is known, run at most `@wai.max_iterations N` times on measured bits), `switch`, `break`, `continue`, `end`; conditions on measured bits with comparisons, `&&`, `||` and `!`, compiled to forward jumps and checked against every value of their bits; `output`, carried into the result; `delay`, `box`, `stretch`, `barrier` and gate durations, carried as timing and labelled in a result whose method applies no durations; `defcal`, `cal` and `defcalgrammar`, kept verbatim and never run; aliases, slices, index sets, physical qubits, `gphase`.
|
||||
- **One grammar**: `quantum_toolchain::from_qasm` (the edge component's and the processor clients' import) reads through the same reader and applies the bit-exact circuit's restriction, refusing with the reader's codes (Q500 a non-dyadic angle, Q501 width, Q502 a dynamic program). A controlled gate the modifiers write stays one gate under all its controls, so `to_qasm`'s output reads back gate for gate. A new feature, `quantum_lang`, holds the reader without the lowerings.
|
||||
- **A job's result** carries `outputs`, a `timing` label (`applied: false`, Q400) and the reader's `diagnostics`, each only when there is one, so a program with none has the result it always had.
|
||||
- **Conformance** (`wai/quantum-conformance/qasm3/`): the specification's 21 example programs, unchanged, and 38 programs for the constructs with references, each with what the reader must do (an exact distribution or outcome, equivalence to a reference, or a code). `stdgates.qasm` holds every standard gate to its definition in `U` and `CX`. Run natively and under wasm32-wasip2 (`wai-quantum-lang.yml`) and in the browser build (`wai-web-wasm.yml`: wasm32 count 8 to 9, native `quantum_engine::` count 14 to 15).
|
||||
- **Feature matrix**: `wai-quantum/docs/qasm-feature-matrix.md`, every construct of OpenQASM 3.1 with what the reader does with it and its code.
|
||||
- **Changed refusals**, each now read: `inv @`, `pow @`, a control on `rz`, `while`, two registers and gate definitions in `from_qasm`; a loop's integer sharing a gate parameter's name; `^` between integers under `OPENQASM 3` (exclusive or). A bare radian number in `from_qasm` is now held to the reader's dyadic tolerance, where a number within 1e-9 of a dyadic angle was rounded to it.
|
||||
|
||||
### wai-quantum: the engine in editors, a language server, a formatter, a grammar and an extension
|
||||
|
||||
The engine where programs are written: any editor that speaks the language server protocol gets its diagnostics, its matrices and counts, and its runs.
|
||||
|
||||
- **The language service** (`engine::editor`), pure and with no protocol in it:
|
||||
- diagnostics: the reader's refusal on its line (one function, `reader_diagnostic`, maps the reader's errors, so stable codes and exact spans plug in there), and the critique's smells on theirs, their kind as the code; a generator read at the given inputs, or 4;
|
||||
- completion by what the cursor's place takes (qubits after a gate's name, values in its parameters, integers in an index, bits after `->`), the standard gates with placeholders, snippets, and sample programs in an empty file;
|
||||
- hover: each standard gate's matrix written exactly, held entry by entry to the engine's own under every name the reader accepts; a user gate's matrix from the engine's matrices of its gates; each gate's cost as the engine counts it (two-qubit gates, T count, depth, Clifford), at the call's angles or generic ones, said which; a register's size;
|
||||
- definitions, references, highlights and renames over an index of declarations and scopes that reads all of OpenQASM 3 and a half-typed program; an outline; folding (blocks, comments, held blocks);
|
||||
- a formatter with one layout that checks it keeps every token, refuses a program whose brackets do not match, and is tested stable and meaning-preserving on a corpus in every part of the language.
|
||||
- **The command line:** `wai-quantum lsp` serves it over standard input and output (UTF-16 or UTF-8 positions, as agreed), with Run, Plan, Critique, Shortcuts and Receipt as lenses run in-process and signed with the user's key; `wai-quantum fmt` formats, `--check`s and `--write`s.
|
||||
- **A tree-sitter grammar** (`wai/tools/tree-sitter-openqasm`): all of OpenQASM 3.1 and OpenQASM 2's forms, its generated parser committed, queries for highlighting, scopes and folds; every program in the repository's conformance material and examples parses with no error.
|
||||
- **The editor extension** (`wai/tools/wai-quantum-editor`): highlighting, the server started from a configurable path with install commands when it is missing, the commands' answers in an output panel, a receipt saved as JSON; packaged as a `.vsix`, not published. Configurations for editors configured in Lua, by `languages.toml`, and with WebAssembly extensions (built for `wasm32-wasip2`).
|
||||
- **CI:** `wai-quantum-editors.yml` runs the service's and the server's tests on Linux and macOS, regenerates the grammar and holds it to the committed parser, parses and formats every program in the repository (formatting twice changes nothing, and the engine draws the same circuit), and packages and checks the extension.
|
||||
|
||||
### wai-quantum: bring your own quantum
|
||||
|
||||
People bring their own quantum hardware, provider accounts, on-premises devices or simulators; WAI gives the engine, the free job service and the verifier, and never pays for or resells hardware time. A run on a person's provider is planned, its cost shown before it is submitted, checked, and sealed like any other job.
|
||||
|
||||
- **The open provider protocol** (`extensions/quantum-providers.md`, `wai.quantum.provider/1`): JSON messages over HTTP or to a local process on its standard input and output; `describe` (native gates, connectivity, qubits, durations, a calibration snapshot id with optional per-qubit and per-pair errors, the billing unit and price or free), `estimate`, `submit`, `status`, `result` (counts keyed by classical bits, the highest first) and `cancel`; a program in the device's own gates, every angle an exact fraction of a turn, with its OpenQASM 3 beside it; error codes; what the receipt proves and what it does not.
|
||||
- **wai-quantum-qpu:**
|
||||
- `open_provider`: the client over either transport (a credential only over https or to this machine; in a process's environment, never its command line), and `OpenProvider`, a `Provider` over it;
|
||||
- `reference`: the reference provider, the protocol around the exact simulator, served both ways (`wai-qpu reference`); free or priced per shot or job in exact decimals, with status polls, a readout error and a credential checked by its hash; the template to copy;
|
||||
- `conformance`: the checker and its vectors (`conformance/provider-v1.json`), the reference's counts pinned; jobs run only when every one is free or the person allows the spend;
|
||||
- `registry`: the person's list (`~/.config/wai/quantum-providers.json`), holding no credential; credentials in the keychain (the system `security` tool, or `secret-tool`), else a 0600 file, labelled so in every listing; environment variables still work;
|
||||
- `job`: the dry run (the exact native compile, the check by simulation, the provider's estimate and billing unit), the refusal of a run that is not free (or of unknown cost) until it is confirmed, and the seal of its counts;
|
||||
- `Provider` gains `details`, `estimate`, `submit_seeded` and `cancel`, each with a default.
|
||||
- **The engine** (`engine::provider`): what a provider job may ask (counts of a program measured at the end, every angle dyadic), the measured result labelled `measured` with the circuit's exact distribution beside it (total variation distance, Hellinger fidelity, and what the shots alone leave), and its seal, which `job::verify` checks. `catalog::read` refuses a job that names a provider, so the job service never runs one on its own methods.
|
||||
- **The command line:** `providers add|list|remove|describe|test|free|reference`, and `run --provider NAME [--dry-run] [--yes]` (a run that is not free exits 3 without `--yes`). The stdio MCP server gains `providers_list`, `provider_estimate` and `run_on_provider`; the last says it can spend the person's money and refuses without `confirm_cost: true` when the run is not free.
|
||||
- **The desktop app:** `providers_list`, `provider_estimate` and `run_on_provider` commands; the Studio's **Your hardware** switch lists the providers, asks for the estimate and shows a dialog before a run that is not free. In a browser tab the switch says such runs go through the desktop app or the command line, since a tab must not hold a credential.
|
||||
- **The job service** never routes to a provider and never takes a credential (its README says so; a job naming one is refused).
|
||||
- **Docs:** `wai-quantum-qpu/bring-your-own-quantum.md` (adding a provider, the protocol, the reference as a template, what the receipt proves and what it does not, and what a person does to connect a real device).
|
||||
- **CI:** `wai-quantum-qpu.yml` pins its three test binaries and the new tests by name, with a macOS leg for the keychain in a keychain file the test makes; `wai-quantum-cli.yml` follows the crate and pins the five end-to-end tests; `wai-quantum-studio.yml` runs the hardware switch's logic test. Nothing in them spends money.
|
||||
|
||||
### wai-quantum: Python and notebooks, in-process
|
||||
|
||||
WAI Quantum from Python and notebooks, with the same answers and receipts as every other surface: the shared job engine in the process, a client for the job service, and notebook widgets.
|
||||
|
||||
- **`wai/wai-quantum-py`** (Python module `wai_quantum`): a pyo3 extension module over the shared job engine, built by maturin into one abi3 wheel per platform, Python 3.9 on.
|
||||
- The engine's functions: `run`, `plan`, `lint`, `draw` (text and SVG), `layout`, `critique`, `improve`, `shortcuts`, `equivalent`, `verify`, `seal`, `canonical`, `digest`, `methods`, `accuracy_classes` and `history`, and `bloch`: each qubit's reduced state from the engine's expectation values of X, Y and Z.
|
||||
- Answers are plain dicts and lists. A job is the service's form, with helpers: `counts`, `probabilities()` (the sampled frequencies), `expectations`, `amplitudes`, `method`, `accuracy` and `receipt`.
|
||||
- Values cross one to one with JSON's: NaN, infinities, integers past 64 bits and keys that are not strings are refused, never guessed at.
|
||||
- A refusal raises `EngineError` with the engine's message and the line it names; its `code` is the reader's stable diagnostic code (`Q103`) when the refusal is the reader's.
|
||||
- **Keys:** a result is sealed with the key the caller passes (`Key`), by default this user's key, which the command line also signs with. The demo key and the key files are the command line's, so the same key signs on both.
|
||||
- **`Service`:** a client in the standard library alone for the job service (`submit`, `status`, `result`, `cancel`, `run`). It names itself `wai-quantum-python/<version>` in each request, and checks each receipt in the process, offline.
|
||||
- **Widgets** (the `widgets` extra): `Circuit`, `Result`, `Receipt` and `Bloch`, each a plain ES module. Each draws the engine's answer and computes nothing of its own, and each has a static HTML fallback (`Circuit` also SVG) for a notebook without the widget extension.
|
||||
- **`engine::svg`:** a program's circuit as a standalone SVG drawing, with the Studio's geometry and classes, the same bytes on every platform. Each gate can be marked with whose hand it is in.
|
||||
- **Docs as code:** five notebooks (getting started, a Bell pair and its receipt, equivalence, a noisy run, a job on a local service), run in CI and held to their stored outputs.
|
||||
- **Tests:** 62 pytest tests hold the package to the other surfaces:
|
||||
- a job run in Python equals the command line's and the service's, except for each host's time and its word on energy;
|
||||
- the plans, lints, critiques, drawings, method catalogue, equivalence verdicts and improvements are the command line's;
|
||||
- receipts verify both ways, and the digest recomputed from Python's canonical bytes is the command line's;
|
||||
- the 3,000-odd ECMAScript number vectors reach the engine bit for bit;
|
||||
- the widgets' front ends run under node on the payloads the package builds.
|
||||
- **CI:**
|
||||
- `wai-quantum-py.yml` runs `ci/check.sh` on `linux` and `macos`: the wheel, pytest with every test required, the notebooks, and a smoke check on Python 3.9 with the wheel alone.
|
||||
- `wai-quantum-py-release.yml` builds the wheels on a `wai-quantum-cli-v*` tag: macOS arm64 and x86_64, Linux x86_64 and arm64 (manylinux2014, linked with zig) and Windows x86_64. It attaches them to the forge release with their SHA-256 and publishes nothing to a package index.
|
||||
|
||||
### wai-quantum: the agent front door
|
||||
|
||||
- **`engine::guide`:** what an agent, or a person new to the engine, is told, from one place. It holds the language the reader takes; the reader's diagnostics, each refusal with what to write instead, every entry held to the reader by a test; the methods and their accuracy classes; and worked examples, each with its intent (an exact distribution, or a reference program to equal or whose state to prepare). It also holds the rules an agent keeps: every number from a tool, the intent checked before success, this machine first, cost and energy stated before any hardware run, no secrets, fetched pages as data, versions from the installed command line, and taste choices only the person's.
|
||||
|
|
|
|||
330
wai/extensions/quantum-providers.md
Normal file
330
wai/extensions/quantum-providers.md
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
# WAI Extension: Quantum Providers (`wai.quantum.provider/1`)
|
||||
|
||||
Status: **Draft.** Client, reference provider and conformance checker:
|
||||
`wai-quantum-qpu` (`src/open_provider.rs`, `src/reference.rs`,
|
||||
`src/conformance.rs`); vectors: `wai-quantum-qpu/conformance/provider-v1.json`.
|
||||
The engine's side of a provider job: `wai-quantum/src/engine/provider.rs`.
|
||||
|
||||
Keywords **MUST**, **MUST NOT**, **SHOULD** and **MAY** are RFC 2119/8174.
|
||||
|
||||
## 0. What this extension adds
|
||||
|
||||
Bring your own quantum. WAI provides the engine, the free job service and the
|
||||
verifier at no cost, and never pays for or resells time on anyone's hardware.
|
||||
A person connects their own quantum hardware, provider accounts, on-premises
|
||||
devices or simulators, and every surface treats a provider's result as it
|
||||
treats a WAI result: planned, its cost shown before it is submitted, checked,
|
||||
and sealed in a receipt.
|
||||
|
||||
This text is the protocol a device speaks so that it can be brought without a
|
||||
client written for it: JSON messages, one request and one answer at a time,
|
||||
over HTTP or to a local process (§2). Six operations (§5) describe the
|
||||
device, estimate a job, submit it, follow it, read its counts and cancel it.
|
||||
A program travels in the device's own native gates, with every angle an exact
|
||||
fraction of a turn (§4), so the program the device runs is the one the client
|
||||
compiled and checked.
|
||||
|
||||
A provider is the program or service that answers the messages. A device is
|
||||
what it runs programs on: a processor, an emulator or a simulator. A client
|
||||
is what sends the messages; a host is the client's process, which holds the
|
||||
person's credential and signing key (the command line, the desktop app).
|
||||
|
||||
## 1. Principles
|
||||
|
||||
1. **The credential stays with the person.** A host keeps a provider's
|
||||
credential in the operating system's keychain (or, where there is none, a
|
||||
file only its owner can read, labelled as such) and sends it only to that
|
||||
provider (§2). A credential MUST NOT appear in a browser page, a log, a
|
||||
receipt, a command line, an answer the host prints, or the hosted job
|
||||
service. The job service never routes a job to a provider and never takes
|
||||
a credential: a request that names a provider is refused there.
|
||||
2. **Cost before submit.** A client MUST show a job's estimate (§5.2) before
|
||||
it submits the job, and MUST NOT submit a job that is not free without the
|
||||
person's explicit confirmation (§7). An unknown cost is not free.
|
||||
3. **Exact programs.** A client compiles a circuit exactly to the device's
|
||||
native gates and connectivity and checks the compiled program against the
|
||||
circuit before sending it. Angles cross the wire exactly (§4).
|
||||
4. **Measured, not recomputed.** A provider's counts are sealed as measured on
|
||||
the device it names (§8). Nothing recomputes them.
|
||||
|
||||
## 2. Transports
|
||||
|
||||
Every message is a JSON object, and so is every answer. A client sends one
|
||||
message and reads its answer before it sends the next on the same transport.
|
||||
|
||||
### 2.1 HTTP
|
||||
|
||||
A message is the body of a `POST` to the provider's endpoint (one URL for
|
||||
every operation), with `Content-Type: application/json`. The answer is the
|
||||
body of a `200` response, also for an answer with `"ok": false` (§3). Any
|
||||
other status is a transport failure, not an answer.
|
||||
|
||||
A credential, when there is one, goes in `Authorization: Bearer <credential>`.
|
||||
A client MUST NOT send a credential over `http://` to any host but this
|
||||
machine (`localhost`, a loopback address); over the network it uses
|
||||
`https://`.
|
||||
|
||||
### 2.2 A local process
|
||||
|
||||
The provider is a program the person names, with its arguments, started by
|
||||
the client without a shell. Each message is one line of JSON on the program's
|
||||
standard input; each answer is one line of JSON on its standard output, in
|
||||
order. The program MUST write nothing else to its standard output. Its
|
||||
standard error is its own log, and a client MAY discard it. The program runs
|
||||
until its standard input ends.
|
||||
|
||||
A credential, when there is one, is in the program's environment as
|
||||
`WAI_PROVIDER_CREDENTIAL`, never on its command line. A client SHOULD NOT
|
||||
pass the program another provider's credential.
|
||||
|
||||
## 3. Messages and errors
|
||||
|
||||
Every message carries:
|
||||
|
||||
| field | |
|
||||
|---|---|
|
||||
| `protocol` | `"wai.quantum.provider/1"` |
|
||||
| `op` | `describe`, `estimate`, `submit`, `status`, `result` or `cancel` |
|
||||
| `settings` | optional: the person's non-secret settings for this provider (a device name, a region), passed as they are |
|
||||
|
||||
and the operation's own fields (§5). Every answer carries `"ok": true` and
|
||||
the operation's fields, or:
|
||||
|
||||
```json
|
||||
{ "ok": false, "error": { "code": "not_found", "message": "no job j-17" } }
|
||||
```
|
||||
|
||||
The `message` is for a person; it MUST NOT quote a credential. The codes:
|
||||
|
||||
| code | when |
|
||||
|---|---|
|
||||
| `invalid` | the message is malformed: a field missing or of the wrong type, a program that does not read (§4), zero shots, a message without `protocol` |
|
||||
| `unsupported` | an operation the provider does not offer (`cancel`, `estimate`), or an `op` it does not know |
|
||||
| `unsupported_version` | a `protocol` other than this one |
|
||||
| `unauthorized` | no credential, or one the provider does not accept |
|
||||
| `not_found` | a job the provider does not hold |
|
||||
| `refused` | a well-formed program the device cannot run: a gate outside its basis, a qubit it does not have, a pair it does not connect, too many shots; or a result asked of a job that has not finished or was cancelled |
|
||||
| `quota` | the person's account cannot pay for or schedule the job |
|
||||
| `unavailable` | the device is offline or in maintenance |
|
||||
| `internal` | anything else |
|
||||
|
||||
## 4. The program
|
||||
|
||||
`estimate` and `submit` carry a `program` in the device's own gates, on its
|
||||
physical qubits:
|
||||
|
||||
```json
|
||||
{
|
||||
"format": "wai.native/1",
|
||||
"basis": "rzsxxcz",
|
||||
"bits": 2,
|
||||
"gates": [
|
||||
{ "gate": "rz", "qubits": [0], "turns": [[1, 2]] },
|
||||
{ "gate": "sx", "qubits": [0] },
|
||||
{ "gate": "cz", "qubits": [0, 1] }
|
||||
],
|
||||
"measure": [{ "qubit": 0, "bit": 0 }, { "qubit": 1, "bit": 1 }],
|
||||
"qasm3": "OPENQASM 3.0; …"
|
||||
}
|
||||
```
|
||||
|
||||
- `basis` is one of three gate sets, and every gate is of it:
|
||||
|
||||
| basis | gates |
|
||||
|---|---|
|
||||
| `rzsxxcz` | `rz(t)`, `sx`, `x`, `cz` |
|
||||
| `prxcz` | `prx(t, p)`, `cz` |
|
||||
| `gpizz` | `gpi(p)`, `gpi2(p)`, `zz(t)` |
|
||||
|
||||
- An angle is a fraction of a full turn, `[m, k]` meaning `m/2^k` of 2π, with
|
||||
`0 ≤ m < 2^k` and `k ≤ 32`, so every angle crosses the wire exactly. The
|
||||
gates, as operators on the named qubits, up to a global phase:
|
||||
- `rz(t)` = exp(−iπt·Z); `sx` = √X; `x` = X; `cz` = diag(1, 1, 1, −1);
|
||||
- `prx(t, p)` = Rz(2πp)·Rx(2πt)·Rz(−2πp);
|
||||
- `gpi(p)` = Rz(2πp)·X·Rz(−2πp); `gpi2(p)` = Rz(2πp)·Rx(π/2)·Rz(−2πp);
|
||||
- `zz(t)` = exp(−iπt·Z⊗Z).
|
||||
- `measure` gives, for each classical bit `0 … bits − 1`, the physical qubit it
|
||||
reads at the end of the program. Every bit reads exactly one qubit, and no
|
||||
qubit is read twice.
|
||||
- `qasm3` is the same program as OpenQASM 3 on physical qubits (`$p`), the
|
||||
`prxcz` and `gpizz` gates defined in it from the standard gates, for a
|
||||
provider that reads OpenQASM. It is informative: where the two differ, the
|
||||
`gates` are the program.
|
||||
|
||||
A provider MUST refuse (`invalid`) a program of another `format`, a gate
|
||||
outside its `basis`, an angle out of range, or a bit that reads no qubit; and
|
||||
(`refused`) a program in a basis its device does not run, or on qubits or
|
||||
pairs it does not have.
|
||||
|
||||
## 5. Operations
|
||||
|
||||
### 5.1 `describe`
|
||||
|
||||
No fields. The answer describes the device:
|
||||
|
||||
| field | |
|
||||
|---|---|
|
||||
| `protocol` | `"wai.quantum.provider/1"` |
|
||||
| `provider`, `device` | the provider's name for itself, and the device's |
|
||||
| `provenance` | `silicon` (a processor), `emulator`, or `simulator`; with `simulator` (or `emulator`) a sentence naming what it is |
|
||||
| `qubits` | the device's qubit count |
|
||||
| `native_gates` | the gates it runs; a client compiles to the first of the bases of §4 whose every gate is listed |
|
||||
| `connectivity` | `"all"`, or the pairs `[a, b]` a two-qubit gate may act on, in either order |
|
||||
| `durations` | optional: `{"unit", "gates", "measure"}`: the unit (`ns`, `us`, `ms` or `s`), each native gate's duration wherever it runs (`{"sx": 35, "cz": 68}`), and the measurement's |
|
||||
| `calibration` | `{"id"}`, the calibration snapshot the device is under; optionally `qubits` (`{"qubit", "readout_error", "error_1q", "t1_us", "t2_us"}`) and `edges` (`{"qubits": [a, b], "error"}`), each error from 0 to 1 |
|
||||
| `billing` | `{"free": true}`, or `{"unit", "price", "currency"}`: the billing unit (`shot`, `job`, `second`, …), the price of one as a decimal string (`"0.0003"`), and the currency or credit it is in; optionally `free_tier`, the free use offered and its limits, as the provider states them |
|
||||
| `max_shots` | optional: the most shots a job may ask |
|
||||
| `seeded` | optional: `true` when a job's `seed` makes its counts reproducible (a simulator) |
|
||||
|
||||
A client MUST NOT take a device to be free unless `billing` says
|
||||
`"free": true`, or an estimate says so (§5.2).
|
||||
|
||||
A client MAY read a `describe` answer whose `calibration` states errors as a
|
||||
device target (`wai.quantum.target/1`, `wai-quantum/src/engine/targets`)
|
||||
and place the program on the qubits and pairs most likely to succeed. The
|
||||
program it sends is checked against the circuit as every program is (§1), and
|
||||
the receipt names how it was placed (§8).
|
||||
|
||||
### 5.2 `estimate`
|
||||
|
||||
Fields: `program` (§4), `shots`. The answer, before anything is submitted:
|
||||
|
||||
| field | |
|
||||
|---|---|
|
||||
| `free` | whether this job is free |
|
||||
| `amount`, `currency` | when it is not: the cost, the amount as a decimal string |
|
||||
| `unit` | optional: the billing unit the cost counts |
|
||||
| `seconds` | optional: how long it is expected to take, queue included |
|
||||
| `note` | optional |
|
||||
|
||||
A provider that cannot estimate answers `unsupported`; the client then treats
|
||||
the cost as unknown (§7).
|
||||
|
||||
### 5.3 `submit`
|
||||
|
||||
Fields: `program`, `shots`, and optionally `seed` (a seeded simulator uses
|
||||
it; a device ignores it). The answer's `job` is the job's id.
|
||||
|
||||
### 5.4 `status`
|
||||
|
||||
Field: `job`. The answer's `status` is `queued`, `running`, `done`, `failed`
|
||||
or `cancelled`, with an optional `reason`.
|
||||
|
||||
### 5.5 `result`
|
||||
|
||||
Field: `job`. The answer, once the job is `done`:
|
||||
|
||||
| field | |
|
||||
|---|---|
|
||||
| `counts` | an object from outcomes to counts (§6), summing to the shots |
|
||||
| `shots` | the shots |
|
||||
| `calibration` | optional: the calibration snapshot the job ran under, when it is not the one `describe` names |
|
||||
| `charged` | optional: `{"amount", "currency"}`, what the job cost |
|
||||
| `energy` | optional: `{"kwh"}`, the provider's own figure for the job's energy |
|
||||
|
||||
A `result` asked twice of the same job MUST give the same counts.
|
||||
|
||||
### 5.6 `cancel`
|
||||
|
||||
Field: `job`. The answer's `status` is `cancelled`, or `done` for a job that
|
||||
had already finished. A provider that cannot cancel answers `unsupported`.
|
||||
|
||||
## 6. Counts and bit order
|
||||
|
||||
An outcome is a string of `bits` characters, `0` or `1`, the highest bit
|
||||
first: its last character is bit 0. `"01"` is bit 0 read as 1 and bit 1 read
|
||||
as 0. This is OpenQASM's order, and the job service's.
|
||||
|
||||
The client compiles each logical qubit `i` of the person's circuit to end on
|
||||
the physical qubit that bit `i` measures, and reads the counts back onto the
|
||||
program's own classical bits. The first job on a new provider SHOULD be the
|
||||
probe (an `X` on qubit 0, every qubit measured), whose counts must all land
|
||||
on `…01`; the conformance vectors begin with it (§9).
|
||||
|
||||
## 7. Cost and confirmation
|
||||
|
||||
A job is free when the provider's estimate says `"free": true`, or, for a
|
||||
provider that gives no estimate, when its `billing` says so. Every other job,
|
||||
an unknown cost included, is not free. A client:
|
||||
|
||||
- MUST show the estimate (or that the cost is unknown) before submitting;
|
||||
- MUST NOT submit a job that is not free without the person's explicit
|
||||
confirmation for that run: a command-line flag (`wai-quantum run --provider
|
||||
NAME --yes`), an agent tool's argument the agent sets only after the person
|
||||
agreed (`run_on_provider` with `confirm_cost: true`), or a dialog (the
|
||||
desktop app);
|
||||
- MUST NOT hold a standing confirmation across runs.
|
||||
|
||||
A tool that can submit a job that is not free MUST say in its description
|
||||
that it can spend the person's money.
|
||||
|
||||
## 8. The receipt
|
||||
|
||||
The host seals each provider job as the job service seals its own: an Ed25519
|
||||
signature, by the host's key, over the request as submitted and the result
|
||||
as returned, each in its RFC 8785 canonical text, verified by the same
|
||||
verifier. The result's `method` is `provider` and its accuracy class is
|
||||
`measured`. It carries:
|
||||
|
||||
- `provider`: the person's name for it, its kind, its protocol, the device,
|
||||
its provenance, and the BLAKE3 hash of its `describe` answer;
|
||||
- `calibration`: the calibration snapshot the job ran under;
|
||||
- `compiled`: the basis, the BLAKE3 hash of the compiled program's OpenQASM 3
|
||||
text, its gate and swap counts, its initial and final layout, the check it
|
||||
passed before it was sent, and how it was placed (`placement`: with a
|
||||
calibration read as a target, the target's hash, the layout's expected
|
||||
success and the fewest-swaps layout's);
|
||||
- `job`: the provider's job id and the status checks before it finished;
|
||||
- `counts`, keyed by the program's classical bits (§6);
|
||||
- `ideal`: the circuit's exact distribution set beside the counts (up to 22
|
||||
qubits): the total variation distance, the Hellinger fidelity, and the
|
||||
distance the shots alone would leave on average;
|
||||
- `cost`: the estimate shown before submitting, what the provider says it
|
||||
charged, and whether the person confirmed a run that was not free;
|
||||
- `energy`: unmetered here, with the provider's own figure, labelled as its
|
||||
own, when it gives one.
|
||||
|
||||
What the receipt proves: that this result, with these counts, is what the
|
||||
signer's host received for this request from the provider and device it
|
||||
names, under the calibration snapshot named, for the compiled program whose
|
||||
hash it carries; and that the host compiled that program exactly and checked
|
||||
it against the circuit before sending it. What it does not prove: that the
|
||||
device ran that program, or ran anything. The counts are the provider's word,
|
||||
and they are not reproducible by recomputation: the same job run again gives
|
||||
other counts. The `ideal` distance says how far they are from what the
|
||||
circuit gives; a distance well above the sampling distance is the device's
|
||||
error, or a program the device did not run as sent.
|
||||
|
||||
## 9. Conformance
|
||||
|
||||
`wai-quantum-qpu/conformance/provider-v1.json` holds the vectors:
|
||||
|
||||
- **messages**, sent as they are: an unknown operation (`unsupported`),
|
||||
another version (`unsupported_version`), a message without its protocol
|
||||
(`invalid`), a job that does not exist (`not_found`), malformed programs
|
||||
(`invalid`);
|
||||
- **programs**, each compiled to the device, estimated, run with seed 1, and
|
||||
checked by its counts: the probe, bits named out of order, a phase only
|
||||
interference shows, a phase kicked back by two quarter-turn controlled
|
||||
phases, a Bell pair, and a triangle of two-qubit gates that needs routing
|
||||
on a line. The thresholds leave room for a device's noise;
|
||||
- **reference**: the counts the reference provider gives for each program at
|
||||
seed 1, so its determinism is held on every platform.
|
||||
|
||||
The checker (`wai-quantum providers test NAME`) also checks the `describe`
|
||||
answer in full, that zero shots are `invalid`, and that a program in another
|
||||
basis is refused. It runs the programs only when every estimate says free,
|
||||
or the person allows the spend (`--yes`).
|
||||
|
||||
The reference provider (`wai-quantum providers reference --stdio`, or
|
||||
`--http ADDR`) is this protocol around WAI's exact simulator. It is the
|
||||
provider the tests run against over both transports, and the template to
|
||||
copy: a provider for any device is the reference with its simulation replaced
|
||||
by the device.
|
||||
|
||||
## 10. Versioning
|
||||
|
||||
`wai.quantum.provider/1` is this text. A later version is a new `protocol`
|
||||
string; a provider that speaks only this one answers `unsupported_version` to
|
||||
another. Fields marked optional may be added to answers without a new
|
||||
version, and a client MUST ignore fields it does not know.
|
||||
|
|
@ -16,6 +16,9 @@ Four trees, each a pinned corpus:
|
|||
| `reject/` + `reject/reject.json` | both | payloads a conforming reader refuses, each with the class it is refused as: `malformed`, `contract` or `invalid` (extension §2) |
|
||||
| `accept/` + `accept/accept.json` | both | payloads a conforming reader accepts, at the edges of the same rules, each with how it reads: capability, `n_qubits`, op count, circuit hash and measurement (extension §2) |
|
||||
|
||||
The OpenQASM 3 reader's corpus, programs with what the reader must do with
|
||||
each, is `qasm3/`, 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
|
||||
against each other.
|
||||
|
|
|
|||
56
wai/quantum-conformance/intents/README.md
Normal file
56
wai/quantum-conformance/intents/README.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Intent conformance
|
||||
|
||||
Programs, what each must do (its intents), and the verdict the engine must
|
||||
give when the program runs as a job with them (`wai_quantum::engine::verdict`,
|
||||
[the verdict page](../../wai-quantum/docs/verdicts.md)).
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `programs/` | The programs and the references their intents name: a Bell pair, GHZ states built two ways, a Grover search written with `cz` and with `cx`, rotations that merge, twelve-qubit circuits that only checked rewrites or random inputs decide, a forty-qubit Clifford pair, a program that acts on what it measured, and programs that do not read until they are repaired. |
|
||||
| `repaired/` | The program a repaired case must run, as the repair writes it. |
|
||||
| `manifest.json` | Each case: its program, its run (the job's other fields), its intents, and what its verdict must say (the manifest's `expect` says what each field means). |
|
||||
| `bundle.json` | The manifest's cases with every program and reference inline, for builds that read no files. |
|
||||
|
||||
A case's verdict is held to its level (`refused`, `parsed`, `executed`,
|
||||
`evidence`, `proof`), to whether its intents hold, and to each intent's
|
||||
outcome, strength and check. A distribution's total variation distance is
|
||||
held within 1e-12 of a value known by hand: 0 for an exact match, 1/2 for a
|
||||
Bell pair against one outcome, and 2 · 0.02 · 0.98 = 0.0392 for a Bell pair
|
||||
whose bits each flip with probability 0.02. A sampled case holds the run's samples to a
|
||||
stated distribution by a stated test at a stated level, at a fixed seed: it is
|
||||
evidence, never proof, and its outcome is held to the manifest's. A refused
|
||||
case is held to the last code its refusal gives. Every level of the ladder has
|
||||
a case.
|
||||
|
||||
## Native
|
||||
|
||||
```sh
|
||||
cd wai/wai-quantum
|
||||
cargo test --release --features full --test intent_conformance
|
||||
```
|
||||
|
||||
Two tests: every case against its verdict, and the bundle held equal to the
|
||||
files. After changing a program or the manifest, write the bundle:
|
||||
|
||||
```sh
|
||||
WAI_INTENT_BUNDLE_WRITE=1 cargo test --release --features full --test intent_conformance the_bundle_is_the_corpus
|
||||
```
|
||||
|
||||
## WASI (the edge)
|
||||
|
||||
```sh
|
||||
CARGO_TARGET_WASM32_WASIP2_RUNNER=wasmtime \
|
||||
cargo test --target wasm32-wasip2 --features full --test intent_conformance
|
||||
```
|
||||
|
||||
The cases come from the bundle compiled into the test.
|
||||
|
||||
## Browser
|
||||
|
||||
wai-web's wasm32 tests (`--features quantum_engine`, under
|
||||
`wasm-bindgen-test-runner`) run every case of the bundle through the page's
|
||||
engine (`QuantumEngine.run`), and work each verdict out again with
|
||||
`engine_verdict`.
|
||||
|
||||
CI: `wai-quantum-verdict.yml` (native and wasm32-wasip2) and
|
||||
`wai-web-wasm.yml` (the browser build).
|
||||
910
wai/quantum-conformance/intents/bundle.json
Normal file
910
wai/quantum-conformance/intents/bundle.json
Normal file
|
|
@ -0,0 +1,910 @@
|
|||
{
|
||||
"format": "wai.quantum-intent-conformance-bundle/1",
|
||||
"about": "manifest.json's cases with every program and reference inline, for builds that read no files (the browser, the edge); a test holds it equal to the files",
|
||||
"cases": [
|
||||
{
|
||||
"name": "bell-distribution",
|
||||
"covers": [
|
||||
"an exact distribution, by the state vector"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-wrong-distribution",
|
||||
"covers": [
|
||||
"a distribution that fails, with its distance"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.5
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-under-readout-noise",
|
||||
"covers": [
|
||||
"a distribution under noise, by the density matrix, within a tolerance"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"noise": {
|
||||
"readout": 0.02
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"tolerance": 0.05
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "density_matrix",
|
||||
"distance": 0.0392
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-under-readout-noise-tight",
|
||||
"covers": [
|
||||
"the same distance past a tighter tolerance"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"noise": {
|
||||
"readout": 0.02
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"tolerance": 0.01
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "density_matrix",
|
||||
"distance": 0.0392
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "ghz-prepares-the-chain-s-state",
|
||||
"covers": [
|
||||
"the same state from |0…0⟩ as a reference"
|
||||
],
|
||||
"program": "programs/ghz.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"prepares": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[4] q;\nbit[4] c;\nh q[0];\ncx q[0], q[1];\ncx q[1], q[2];\ncx q[2], q[3];\nc = measure q;\n",
|
||||
"name": "programs/ghz-chain.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "state"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[4] q;\nbit[4] c;\nh q[0];\ncx q[0], q[1];\ncx q[0], q[2];\ncx q[1], q[3];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "ghz-is-not-the-chain-s-circuit",
|
||||
"covers": [
|
||||
"the same state but not the same circuit: decided by tableau"
|
||||
],
|
||||
"program": "programs/ghz.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[4] q;\nbit[4] c;\nh q[0];\ncx q[0], q[1];\ncx q[1], q[2];\ncx q[2], q[3];\nc = measure q;\n",
|
||||
"name": "programs/ghz-chain.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "tableau"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[4] q;\nbit[4] c;\nh q[0];\ncx q[0], q[1];\ncx q[0], q[2];\ncx q[1], q[3];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "grover-two-intents",
|
||||
"covers": [
|
||||
"two intents, both by proof"
|
||||
],
|
||||
"program": "programs/grover.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q;\nh q[1];\ncx q[0], q[1];\nh q[1];\nh q;\nx q;\nh q[1];\ncx q[0], q[1];\nh q[1];\nx q;\nh q;\nc = measure q;\n",
|
||||
"name": "programs/grover-cx.qasm"
|
||||
},
|
||||
{
|
||||
"distribution": {
|
||||
"11": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "tableau"
|
||||
},
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q;\ncz q[0], q[1];\nh q;\nx q;\ncz q[0], q[1];\nx q;\nh q;\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "rotations-merge",
|
||||
"covers": [
|
||||
"off the Clifford angles, on every basis state"
|
||||
],
|
||||
"program": "programs/rz-pair.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z0 Z1"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nh q;\nrz(0.7) q[0];\ncx q[0], q[1];\n",
|
||||
"name": "programs/rz-merged.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nh q;\nrz(0.3) q[0];\nrz(0.4) q[0];\ncx q[0], q[1];\n"
|
||||
},
|
||||
{
|
||||
"name": "rotations-that-differ",
|
||||
"covers": [
|
||||
"a small difference in an angle, found on every basis state"
|
||||
],
|
||||
"program": "programs/rz-pair.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z0 Z1"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nh q;\nrz(0.71) q[0];\ncx q[0], q[1];\n",
|
||||
"name": "programs/rz-near.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nh q;\nrz(0.3) q[0];\nrz(0.4) q[0];\ncx q[0], q[1];\n"
|
||||
},
|
||||
{
|
||||
"name": "a-relative-phase",
|
||||
"covers": [
|
||||
"a relative phase is a difference"
|
||||
],
|
||||
"program": "programs/relative-phase.qasm",
|
||||
"run": {
|
||||
"amplitudes": [
|
||||
"0",
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nh q[0];\n",
|
||||
"name": "programs/plus.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nh q[0];\nrz(0.2) q[0];\n"
|
||||
},
|
||||
{
|
||||
"name": "wide-by-rewrites",
|
||||
"covers": [
|
||||
"wider than every basis state, proved by checked rewrites"
|
||||
],
|
||||
"program": "programs/wide-merge.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\nrx(0.75) q[3];\ncx q[3], q[9];\nrz(1.1) q[11];\n",
|
||||
"name": "programs/wide-merged.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "rewrites"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\nrx(0.25) q[3];\nrx(0.5) q[3];\ncx q[3], q[9];\nrz(1.1) q[11];\n"
|
||||
},
|
||||
{
|
||||
"name": "wide-by-random-inputs",
|
||||
"covers": [
|
||||
"evidence, not proof: random product states"
|
||||
],
|
||||
"program": "programs/wide-swap.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\ncx q[3], q[9];\ncx q[9], q[3];\ncx q[3], q[9];\nrz(1.1) q[11];\n",
|
||||
"name": "programs/wide-swap-cx.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "random"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\nswap q[3], q[9];\nrz(1.1) q[11];\n"
|
||||
},
|
||||
{
|
||||
"name": "wide-proof-required",
|
||||
"covers": [
|
||||
"evidence counted as unchecked when proof is required"
|
||||
],
|
||||
"program": "programs/wide-swap.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\ncx q[3], q[9];\ncx q[9], q[3];\ncx q[3], q[9];\nrz(1.1) q[11];\n",
|
||||
"require": "proof",
|
||||
"name": "programs/wide-swap-cx.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "unchecked",
|
||||
"strength": "none",
|
||||
"how": "random"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\nswap q[3], q[9];\nrz(1.1) q[11];\n"
|
||||
},
|
||||
{
|
||||
"name": "evidence-and-proof",
|
||||
"covers": [
|
||||
"the level is the weakest check"
|
||||
],
|
||||
"program": "programs/wide-swap.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\ncx q[3], q[9];\ncx q[9], q[3];\ncx q[3], q[9];\nrz(1.1) q[11];\n",
|
||||
"name": "programs/wide-swap-cx.qasm"
|
||||
},
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\nswap q[3], q[9];\nrz(1.1) q[11];\n",
|
||||
"name": "programs/wide-swap.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "random"
|
||||
},
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[12] q;\nh q;\nswap q[3], q[9];\nrz(1.1) q[11];\n"
|
||||
},
|
||||
{
|
||||
"name": "clifford-at-forty-qubits",
|
||||
"covers": [
|
||||
"Clifford circuits at any width, by tableau"
|
||||
],
|
||||
"program": "programs/clifford40.qasm",
|
||||
"run": {
|
||||
"shots": 10
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[40] q;\nh q;\ns q[7];\ncz q[39], q[0];\n",
|
||||
"name": "programs/clifford40-reordered.qasm"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "tableau"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[40] q;\nh q;\ncz q[0], q[39];\ns q[7];\n"
|
||||
},
|
||||
{
|
||||
"name": "feedback-is-unchecked",
|
||||
"covers": [
|
||||
"a program that acts on what it measured: its distribution unchecked"
|
||||
],
|
||||
"program": "programs/feedback.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "unchecked",
|
||||
"strength": "none",
|
||||
"how": "none"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\nc[0] = measure q[0];\nif (c[0]) x q[1];\nc[1] = measure q[1];\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled",
|
||||
"covers": [
|
||||
"samples held to a distribution by Pearson's chi-squared test: evidence, never proof"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 7
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.01,
|
||||
"shots": 4000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-biased",
|
||||
"covers": [
|
||||
"a biased claim rejected by the G-test"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 7
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.6,
|
||||
"11": 0.4
|
||||
},
|
||||
"test": "g_test",
|
||||
"alpha": 0.01,
|
||||
"shots": 4000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "evidence",
|
||||
"how": "g_test"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-ruled-out",
|
||||
"covers": [
|
||||
"an outcome the claim gives probability 0, sampled: fails outright"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 1.0
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.05,
|
||||
"shots": 100
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "evidence",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-proof-required",
|
||||
"covers": [
|
||||
"a statistical test counted as unchecked when proof is required"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.01,
|
||||
"shots": 1000,
|
||||
"require": "proof"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "unchecked",
|
||||
"strength": "none",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-under-readout-noise",
|
||||
"covers": [
|
||||
"samples under the job's noise, held to its exact noisy distribution"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 3,
|
||||
"noise": {
|
||||
"readout": 0.02
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.4804,
|
||||
"01": 0.0196,
|
||||
"10": 0.0196,
|
||||
"11": 0.4804
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.001,
|
||||
"shots": 20000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "proof-and-a-test",
|
||||
"covers": [
|
||||
"the level is the weakest check: an exact distribution and a test of samples"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 7
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"test": "g_test",
|
||||
"alpha": 0.01,
|
||||
"shots": 2000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
},
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "g_test"
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "no-intent",
|
||||
"covers": [
|
||||
"a verdict asked for with no intent"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"verdict": true
|
||||
},
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [],
|
||||
"method": "stabilizer"
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "compiled-first",
|
||||
"covers": [
|
||||
"a run compiled to Clifford+T, its intent checked on the program"
|
||||
],
|
||||
"program": "programs/rotation.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"compile": {
|
||||
"epsilon": 0.001
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 0.75,
|
||||
"1": 0.25
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"method": "exact",
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nbit[1] c;\nrx(pi/3) q[0];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "repaired-first",
|
||||
"covers": [
|
||||
"a missing `;` and a measurement with no target, repaired before the run"
|
||||
],
|
||||
"program": "programs/bell-broken.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"repair": true
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"repairs": [
|
||||
"Q004",
|
||||
"Q320"
|
||||
],
|
||||
"repaired": "bell-repaired",
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nmeasure q;\n",
|
||||
"repaired_qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
},
|
||||
{
|
||||
"name": "a-bound-chosen",
|
||||
"covers": [
|
||||
"an unbounded while, given the bound the person chose"
|
||||
],
|
||||
"program": "programs/unbounded.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"repair": {
|
||||
"max_iterations": 4
|
||||
},
|
||||
"verdict": true
|
||||
},
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"repairs": [
|
||||
"Q310"
|
||||
],
|
||||
"intents": []
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nbit[1] c;\nh q[0];\nc[0] = measure q[0];\nwhile (c[0]) {\n reset q[0];\n h q[0];\n c[0] = measure q[0];\n}\n"
|
||||
},
|
||||
{
|
||||
"name": "a-bound-not-chosen",
|
||||
"covers": [
|
||||
"an unbounded while with no bound chosen: refused with its code"
|
||||
],
|
||||
"program": "programs/unbounded.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"repair": true
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "refused",
|
||||
"code": "Q310"
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nbit[1] c;\nh q[0];\nc[0] = measure q[0];\nwhile (c[0]) {\n reset q[0];\n h q[0];\n c[0] = measure q[0];\n}\n"
|
||||
},
|
||||
{
|
||||
"name": "a-program-that-does-not-read",
|
||||
"covers": [
|
||||
"refused by the reader: nothing runs"
|
||||
],
|
||||
"program": "programs/unknown-gate.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "refused",
|
||||
"code": "Q103"
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nfoo q[0];\n"
|
||||
},
|
||||
{
|
||||
"name": "an-intent-that-does-not-read",
|
||||
"covers": [
|
||||
"an intent whose outcomes are not the program's bits"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "parsed",
|
||||
"code": "J020"
|
||||
},
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
901
wai/quantum-conformance/intents/manifest.json
Normal file
901
wai/quantum-conformance/intents/manifest.json
Normal file
|
|
@ -0,0 +1,901 @@
|
|||
{
|
||||
"format": "wai.quantum-intent-conformance/1",
|
||||
"about": "Programs, what each must do (its intents), and the verdict the engine must give: the level, whether the intents hold, each intent's outcome, strength, check and distance. A sampled intent holds the run's samples to a stated distribution by a stated test: evidence, never proof. The distances are known by hand: 0 for an exact match, 1/2 for a Bell pair against one outcome, 2·0.02·0.98 = 0.0392 for a Bell pair whose bits each flip with 0.02.",
|
||||
"expect": {
|
||||
"level": "the verdict's level: refused, parsed, executed, evidence or proof",
|
||||
"holds": "whether the intents held: true, false, or null when one was not decided",
|
||||
"intents": "each intent's outcome (holds, fails, unchecked), strength (proof, evidence, none), check (how: for a sampled intent, its test) and, for a distribution, its total variation distance within 1e-12",
|
||||
"code": "for a job refused: the last code its refusal gives",
|
||||
"method": "the method the run took",
|
||||
"repairs": "the codes of the repairs made before the run, in order",
|
||||
"repaired": "the program the run took, in repaired/NAME.qasm"
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"name": "bell-distribution",
|
||||
"covers": [
|
||||
"an exact distribution, by the state vector"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-wrong-distribution",
|
||||
"covers": [
|
||||
"a distribution that fails, with its distance"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-under-readout-noise",
|
||||
"covers": [
|
||||
"a distribution under noise, by the density matrix, within a tolerance"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"noise": {
|
||||
"readout": 0.02
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"tolerance": 0.05
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "density_matrix",
|
||||
"distance": 0.0392
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-under-readout-noise-tight",
|
||||
"covers": [
|
||||
"the same distance past a tighter tolerance"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"noise": {
|
||||
"readout": 0.02
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"tolerance": 0.01
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "density_matrix",
|
||||
"distance": 0.0392
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ghz-prepares-the-chain-s-state",
|
||||
"covers": [
|
||||
"the same state from |0…0⟩ as a reference"
|
||||
],
|
||||
"program": "programs/ghz.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"prepares": {
|
||||
"file": "programs/ghz-chain.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "state"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ghz-is-not-the-chain-s-circuit",
|
||||
"covers": [
|
||||
"the same state but not the same circuit: decided by tableau"
|
||||
],
|
||||
"program": "programs/ghz.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/ghz-chain.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "tableau"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "grover-two-intents",
|
||||
"covers": [
|
||||
"two intents, both by proof"
|
||||
],
|
||||
"program": "programs/grover.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/grover-cx.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"distribution": {
|
||||
"11": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "tableau"
|
||||
},
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rotations-merge",
|
||||
"covers": [
|
||||
"off the Clifford angles, on every basis state"
|
||||
],
|
||||
"program": "programs/rz-pair.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z0 Z1"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/rz-merged.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rotations-that-differ",
|
||||
"covers": [
|
||||
"a small difference in an angle, found on every basis state"
|
||||
],
|
||||
"program": "programs/rz-pair.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z0 Z1"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/rz-near.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a-relative-phase",
|
||||
"covers": [
|
||||
"a relative phase is a difference"
|
||||
],
|
||||
"program": "programs/relative-phase.qasm",
|
||||
"run": {
|
||||
"amplitudes": [
|
||||
"0",
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/plus.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "proof",
|
||||
"how": "exact"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wide-by-rewrites",
|
||||
"covers": [
|
||||
"wider than every basis state, proved by checked rewrites"
|
||||
],
|
||||
"program": "programs/wide-merge.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/wide-merged.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "rewrites"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wide-by-random-inputs",
|
||||
"covers": [
|
||||
"evidence, not proof: random product states"
|
||||
],
|
||||
"program": "programs/wide-swap.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/wide-swap-cx.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "random"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wide-proof-required",
|
||||
"covers": [
|
||||
"evidence counted as unchecked when proof is required"
|
||||
],
|
||||
"program": "programs/wide-swap.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/wide-swap-cx.qasm"
|
||||
},
|
||||
"require": "proof"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "unchecked",
|
||||
"strength": "none",
|
||||
"how": "random"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "evidence-and-proof",
|
||||
"covers": [
|
||||
"the level is the weakest check"
|
||||
],
|
||||
"program": "programs/wide-swap.qasm",
|
||||
"run": {
|
||||
"observables": [
|
||||
"Z3"
|
||||
]
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/wide-swap-cx.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/wide-swap.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "random"
|
||||
},
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "clifford-at-forty-qubits",
|
||||
"covers": [
|
||||
"Clifford circuits at any width, by tableau"
|
||||
],
|
||||
"program": "programs/clifford40.qasm",
|
||||
"run": {
|
||||
"shots": 10
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"equivalent": {
|
||||
"file": "programs/clifford40-reordered.qasm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "tableau"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "feedback-is-unchecked",
|
||||
"covers": [
|
||||
"a program that acts on what it measured: its distribution unchecked"
|
||||
],
|
||||
"program": "programs/feedback.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "unchecked",
|
||||
"strength": "none",
|
||||
"how": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled",
|
||||
"covers": [
|
||||
"samples held to a distribution by Pearson's chi-squared test: evidence, never proof"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 7
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.01,
|
||||
"shots": 4000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-biased",
|
||||
"covers": [
|
||||
"a biased claim rejected by the G-test"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 7
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.6,
|
||||
"11": 0.4
|
||||
},
|
||||
"test": "g_test",
|
||||
"alpha": 0.01,
|
||||
"shots": 4000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "evidence",
|
||||
"how": "g_test"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-ruled-out",
|
||||
"covers": [
|
||||
"an outcome the claim gives probability 0, sampled: fails outright"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 1.0
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.05,
|
||||
"shots": 100
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": false,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "fails",
|
||||
"strength": "evidence",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-proof-required",
|
||||
"covers": [
|
||||
"a statistical test counted as unchecked when proof is required"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.01,
|
||||
"shots": 1000,
|
||||
"require": "proof"
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "unchecked",
|
||||
"strength": "none",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "bell-sampled-under-readout-noise",
|
||||
"covers": [
|
||||
"samples under the job's noise, held to its exact noisy distribution"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 3,
|
||||
"noise": {
|
||||
"readout": 0.02
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.4804,
|
||||
"01": 0.0196,
|
||||
"10": 0.0196,
|
||||
"11": 0.4804
|
||||
},
|
||||
"test": "chi_squared",
|
||||
"alpha": 0.001,
|
||||
"shots": 20000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "chi_squared"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "proof-and-a-test",
|
||||
"covers": [
|
||||
"the level is the weakest check: an exact distribution and a test of samples"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"seed": 7
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"sampled": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
},
|
||||
"test": "g_test",
|
||||
"alpha": 0.01,
|
||||
"shots": 2000
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "evidence",
|
||||
"holds": true,
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
},
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "evidence",
|
||||
"how": "g_test"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "no-intent",
|
||||
"covers": [
|
||||
"a verdict asked for with no intent"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"verdict": true
|
||||
},
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"intents": [],
|
||||
"method": "stabilizer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "compiled-first",
|
||||
"covers": [
|
||||
"a run compiled to Clifford+T, its intent checked on the program"
|
||||
],
|
||||
"program": "programs/rotation.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"compile": {
|
||||
"epsilon": 0.001
|
||||
}
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 0.75,
|
||||
"1": 0.25
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"method": "exact",
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "repaired-first",
|
||||
"covers": [
|
||||
"a missing `;` and a measurement with no target, repaired before the run"
|
||||
],
|
||||
"program": "programs/bell-broken.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"repair": true
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"00": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "proof",
|
||||
"holds": true,
|
||||
"repairs": [
|
||||
"Q004",
|
||||
"Q320"
|
||||
],
|
||||
"repaired": "bell-repaired",
|
||||
"intents": [
|
||||
{
|
||||
"outcome": "holds",
|
||||
"strength": "proof",
|
||||
"how": "statevector",
|
||||
"distance": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a-bound-chosen",
|
||||
"covers": [
|
||||
"an unbounded while, given the bound the person chose"
|
||||
],
|
||||
"program": "programs/unbounded.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"repair": {
|
||||
"max_iterations": 4
|
||||
},
|
||||
"verdict": true
|
||||
},
|
||||
"expect": {
|
||||
"level": "executed",
|
||||
"holds": null,
|
||||
"repairs": [
|
||||
"Q310"
|
||||
],
|
||||
"intents": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a-bound-not-chosen",
|
||||
"covers": [
|
||||
"an unbounded while with no bound chosen: refused with its code"
|
||||
],
|
||||
"program": "programs/unbounded.qasm",
|
||||
"run": {
|
||||
"shots": 100,
|
||||
"repair": true
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "refused",
|
||||
"code": "Q310"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "a-program-that-does-not-read",
|
||||
"covers": [
|
||||
"refused by the reader: nothing runs"
|
||||
],
|
||||
"program": "programs/unknown-gate.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "refused",
|
||||
"code": "Q103"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "an-intent-that-does-not-read",
|
||||
"covers": [
|
||||
"an intent whose outcomes are not the program's bits"
|
||||
],
|
||||
"program": "programs/bell.qasm",
|
||||
"run": {
|
||||
"shots": 100
|
||||
},
|
||||
"intent": [
|
||||
{
|
||||
"distribution": {
|
||||
"0": 1.0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expect": {
|
||||
"level": "parsed",
|
||||
"code": "J020"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q
|
||||
bit[2] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
measure q;
|
||||
7
wai/quantum-conformance/intents/programs/bell.qasm
Normal file
7
wai/quantum-conformance/intents/programs/bell.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;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[40] q;
|
||||
h q;
|
||||
s q[7];
|
||||
cz q[39], q[0];
|
||||
6
wai/quantum-conformance/intents/programs/clifford40.qasm
Normal file
6
wai/quantum-conformance/intents/programs/clifford40.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[40] q;
|
||||
h q;
|
||||
cz q[0], q[39];
|
||||
s q[7];
|
||||
8
wai/quantum-conformance/intents/programs/feedback.qasm
Normal file
8
wai/quantum-conformance/intents/programs/feedback.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[2] c;
|
||||
h q[0];
|
||||
c[0] = measure q[0];
|
||||
if (c[0]) x q[1];
|
||||
c[1] = measure q[1];
|
||||
9
wai/quantum-conformance/intents/programs/ghz-chain.qasm
Normal file
9
wai/quantum-conformance/intents/programs/ghz-chain.qasm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[4] q;
|
||||
bit[4] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
cx q[1], q[2];
|
||||
cx q[2], q[3];
|
||||
c = measure q;
|
||||
9
wai/quantum-conformance/intents/programs/ghz.qasm
Normal file
9
wai/quantum-conformance/intents/programs/ghz.qasm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[4] q;
|
||||
bit[4] c;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
cx q[0], q[2];
|
||||
cx q[1], q[3];
|
||||
c = measure q;
|
||||
16
wai/quantum-conformance/intents/programs/grover-cx.qasm
Normal file
16
wai/quantum-conformance/intents/programs/grover-cx.qasm
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[2] c;
|
||||
h q;
|
||||
h q[1];
|
||||
cx q[0], q[1];
|
||||
h q[1];
|
||||
h q;
|
||||
x q;
|
||||
h q[1];
|
||||
cx q[0], q[1];
|
||||
h q[1];
|
||||
x q;
|
||||
h q;
|
||||
c = measure q;
|
||||
12
wai/quantum-conformance/intents/programs/grover.qasm
Normal file
12
wai/quantum-conformance/intents/programs/grover.qasm
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
bit[2] c;
|
||||
h q;
|
||||
cz q[0], q[1];
|
||||
h q;
|
||||
x q;
|
||||
cz q[0], q[1];
|
||||
x q;
|
||||
h q;
|
||||
c = measure q;
|
||||
4
wai/quantum-conformance/intents/programs/plus.qasm
Normal file
4
wai/quantum-conformance/intents/programs/plus.qasm
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[1] q;
|
||||
h q[0];
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[1] q;
|
||||
h q[0];
|
||||
rz(0.2) q[0];
|
||||
6
wai/quantum-conformance/intents/programs/rotation.qasm
Normal file
6
wai/quantum-conformance/intents/programs/rotation.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[1] q;
|
||||
bit[1] c;
|
||||
rx(pi/3) q[0];
|
||||
c = measure q;
|
||||
6
wai/quantum-conformance/intents/programs/rz-merged.qasm
Normal file
6
wai/quantum-conformance/intents/programs/rz-merged.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
h q;
|
||||
rz(0.7) q[0];
|
||||
cx q[0], q[1];
|
||||
6
wai/quantum-conformance/intents/programs/rz-near.qasm
Normal file
6
wai/quantum-conformance/intents/programs/rz-near.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
h q;
|
||||
rz(0.71) q[0];
|
||||
cx q[0], q[1];
|
||||
7
wai/quantum-conformance/intents/programs/rz-pair.qasm
Normal file
7
wai/quantum-conformance/intents/programs/rz-pair.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[2] q;
|
||||
h q;
|
||||
rz(0.3) q[0];
|
||||
rz(0.4) q[0];
|
||||
cx q[0], q[1];
|
||||
11
wai/quantum-conformance/intents/programs/unbounded.qasm
Normal file
11
wai/quantum-conformance/intents/programs/unbounded.qasm
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[1] q;
|
||||
bit[1] c;
|
||||
h q[0];
|
||||
c[0] = measure q[0];
|
||||
while (c[0]) {
|
||||
reset q[0];
|
||||
h q[0];
|
||||
c[0] = measure q[0];
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[1] q;
|
||||
foo q[0];
|
||||
8
wai/quantum-conformance/intents/programs/wide-merge.qasm
Normal file
8
wai/quantum-conformance/intents/programs/wide-merge.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[12] q;
|
||||
h q;
|
||||
rx(0.25) q[3];
|
||||
rx(0.5) q[3];
|
||||
cx q[3], q[9];
|
||||
rz(1.1) q[11];
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[12] q;
|
||||
h q;
|
||||
rx(0.75) q[3];
|
||||
cx q[3], q[9];
|
||||
rz(1.1) q[11];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[12] q;
|
||||
h q;
|
||||
cx q[3], q[9];
|
||||
cx q[9], q[3];
|
||||
cx q[3], q[9];
|
||||
rz(1.1) q[11];
|
||||
6
wai/quantum-conformance/intents/programs/wide-swap.qasm
Normal file
6
wai/quantum-conformance/intents/programs/wide-swap.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
qubit[12] q;
|
||||
h q;
|
||||
swap q[3], q[9];
|
||||
rz(1.1) q[11];
|
||||
|
|
@ -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/qasm3/README.md
Normal file
52
wai/quantum-conformance/qasm3/README.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# OpenQASM 3 conformance
|
||||
|
||||
OpenQASM 3 programs, each with what the reader (`wai_quantum::qasm`) must do
|
||||
with it: read it to an exact result, read it to the unitary of a reference
|
||||
program, or refuse it with a given diagnostic code.
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `spec/` | The OpenQASM 3 specification's example programs, unchanged (Apache-2.0, as the specification is published). Those that run are held to their results; those that cannot be run exactly are held to the code the reader refuses them with, which names the first construct it cannot hold (an `extern`, `durationof`, a `while` on measured bits with no bound) or the example's own error (`arrays.qasm` indexes past its array; `cphase.qasm` and `defcal.qasm` are fragments that declare no qubits). |
|
||||
| `lang/` | A program for each construct the reader lowers, carries, preserves or refuses, and `*.ref.qasm` references written without the construct. `stdgates.qasm` applies every standard gate once; its reference writes each in `U` and `CX` alone. |
|
||||
| `manifest.json` | Each case: its file, what it covers, and its expectations (the manifest's `expectations` says what each kind means). |
|
||||
| `bundle.json` | The manifest's cases with each program's text inline, for builds that read no files. |
|
||||
|
||||
An expectation is one or more of: `refused` (a code), `warns` (the codes of
|
||||
every warning and note, sorted), `deterministic` (every shot's outcome),
|
||||
`distribution` (exact outcome probabilities, within 1e-9), `expectations`
|
||||
(exact Pauli expectation values), `equivalent` (the reference's unitary, up to a
|
||||
global phase, within 1e-9), `exact` (the bit-exact circuit takes it, or refuses
|
||||
it with a code), `outputs`, `timing` and `calibrations`.
|
||||
|
||||
## Native
|
||||
|
||||
```sh
|
||||
cd wai/wai-quantum
|
||||
cargo test --release --features full --test qasm3_conformance
|
||||
```
|
||||
|
||||
Two tests: every case against its expectations, and the bundle held equal to
|
||||
the files. After changing a program or the manifest, write the bundle:
|
||||
|
||||
```sh
|
||||
WAI_QASM3_BUNDLE_WRITE=1 cargo test --release --features full --test qasm3_conformance the_bundle_is_the_corpus
|
||||
```
|
||||
|
||||
## WASI (the edge)
|
||||
|
||||
```sh
|
||||
CARGO_TARGET_WASM32_WASIP2_RUNNER=wasmtime \
|
||||
cargo test --target wasm32-wasip2 --features full --test qasm3_conformance
|
||||
```
|
||||
|
||||
The cases come from the bundle compiled into the test.
|
||||
|
||||
## Browser
|
||||
|
||||
wai-web's wasm32 tests (`--features quantum_engine`, under
|
||||
`wasm-bindgen-test-runner`) read every case of the bundle through the page's
|
||||
engine: each refusal's code, each program's warnings, and each program with one
|
||||
outcome run to it.
|
||||
|
||||
CI: `wai-quantum-lang.yml` (native and wasm32-wasip2) and `wai-web-wasm.yml`
|
||||
(the browser build).
|
||||
525
wai/quantum-conformance/qasm3/bundle.json
Normal file
525
wai/quantum-conformance/qasm3/bundle.json
Normal file
|
|
@ -0,0 +1,525 @@
|
|||
{
|
||||
"format": "wai.qasm3-conformance-bundle/1",
|
||||
"about": "manifest.json's cases with each program's text inline, for builds that read no files (the browser, the edge); a test holds it equal to the files",
|
||||
"cases": [
|
||||
{
|
||||
"file": "spec/adder.qasm",
|
||||
"qasm": "/*\n * quantum ripple-carry adder\n * Cuccaro et al, quant-ph/0410184\n */\ninclude \"stdgates.inc\";\n\ngate majority a, b, c {\n cx c, b;\n cx c, a;\n ccx a, b, c;\n}\n\ngate unmaj a, b, c {\n ccx a, b, c;\n cx c, a;\n cx a, b;\n}\n\nqubit[1] cin;\nqubit[4] a;\nqubit[4] b;\nqubit[1] cout;\nbit[5] ans;\nuint[4] a_in = 1; // a = 0001\nuint[4] b_in = 15; // b = 1111\n// initialize qubits\nreset cin;\nreset a;\nreset b;\nreset cout;\n\n// set input states\nfor uint i in [0: 3] {\n if(bool(a_in[i])) x a[i];\n if(bool(b_in[i])) x b[i];\n}\n// add a to b, storing result in b\nmajority cin[0], b[0], a[0];\nfor uint i in [0: 2] { majority a[i], b[i + 1], a[i + 1]; }\ncx a[3], cout[0];\nfor uint i in [2: -1: 0] { unmaj a[i],b[i+1],a[i+1]; }\nunmaj cin[0], b[0], a[0];\nmeasure b[0:3] -> ans[0:3];\nmeasure cout[0] -> ans[4];\n",
|
||||
"expect": {
|
||||
"deterministic": "10000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/alignment.qasm",
|
||||
"qasm": "/* CPMG XY4 decoupling\n * This example demonstrates the use of stretch to\n * specify design intent on gate alignment, without\n * being tied to physical qubits and gates.\n*/\ninclude \"stdgates.inc\";\n\nstretch g;\n\nqubit[3] q;\nbarrier q;\ncx q[0], q[1];\ndelay[g] q[2];\nU(pi/4, 0, pi/2) q[2];\ndelay[2*g] q[2];\nbarrier q;\n",
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q403"
|
||||
],
|
||||
"timing": true,
|
||||
"distribution": {
|
||||
"000": 0.8535533905932737,
|
||||
"100": 0.14644660940672624
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/arrays.qasm",
|
||||
"qasm": "OPENQASM 3.0; // Version statement is optional\n\n// ==================\n// Array declarations\n// ==================\n\n// Declare 'my_ints' to be a 1D array of 8-bit signed integers, where the index\n// runs from 0 to 15.\narray[int[8], 16] my_ints;\n\n// Declare 'my_doubles' to be a 2D array of double-precision floating-point\n// values, where the first index runs from 0 to 7 and the second from 0 to 3.\narray[float[64], 8, 4] my_doubles;\n\n// Initialise a 1D array with fixed values.\narray[uint[32], 4] my_defined_uints = {5, 6, 7, 8};\n\n// Initialise a 2D array with fixed values.\narray[float[32], 4, 2] my_defined_floats = {\n {0.5, 0.5},\n {1.0, 2.0},\n {-0.4, 0.7},\n {1.3, -2.1e-2}\n};\n\n// Initialise an array using a row of another array. Note that this copies the\n// data; changes to the values in `my_defined_float_row` will not affect\n// `my_defined_floats`.\narray[float[32], 2] my_defined_float_row = my_defined_floats[0];\n\n// Arrays can be defined in terms of compile-time constant dimension sizes, and\n// can use expressions in the slots of their initialisers.\nconst uint[8] DIM_SIZE = 2;\narray[int[8], DIM_SIZE, DIM_SIZE] all_ones = {{2+3, 4-1}, {3+8, 12-4}};\n\n\n// =============================\n// Array indexing and operations\n// =============================\n\n// Use `[]` notation to access array elements. The dimensions are\n// comma-separated.\nuint[8] a = my_defined_uints[0];\nfloat[32] b = my_defined_floats[2, 1];\n\n// The same notation is used in simple assignments.\nmy_defined_uints[1] = 5;\nmy_defined_floats[3, 0] = -0.45;\n\n// In both, the indices can be (non-constant) expressions.\nmy_defined_uints[a - 1] = a + 1;\n\n// Assignments can also be done using an array, or array slice, on the left-hand\n// side, provided the right-hand side evaluates to an array of exactly the same\n// shape. The assignment is done by copy, so subsequent changes to either of\n// the two parts will not affect the other.\nmy_defined_floats[2] = my_defined_float_row;\n\n// You can also use the slice notation to set elements. Beware that it is\n// generally a logical error to read and write from overlapping slices at the\n// same time, and that OpenQASM 3 makes no guarantees about which order the data\n// will be read from and written to. You might clobber data if you overlap.\nmy_defined_floats[0:1] = my_defined_floats[2:3];\n\n// The ``sizeof`` operator returns the size of an array's dimension.\nconst uint[32] dimension = sizeof(my_defined_uints); // assigns 4.\n\n// The ``sizeof`` operator can also be used in two-argument form, where the\n// second argument is the index of the dimension, counting from 0.\nconst uint[32] first_dimension = sizeof(my_doubles, 0); // returns 8\nconst uint[32] second_dimension = sizeof(my_doubles, 1); // returns 4\n\n// If the second argument is omitted from ``sizeof`` and the given array is\n// multi-dimensional, it defaults to returning the first dimension, so\n// ``sizeof(my_array) == sizeof(my_array, 0)`` in all circumstances.\nconst uint[32] first_dimension = sizeof(my_doubles); // still 8.\n\n\n// =====================\n// Arrays in subroutines\n// =====================\n\n// Array arguments have a mandatory ``readonly`` or ``mutable`` specifier when\n// defined in a subroutine argument list. This is because arrays are passed to\n// subroutines by reference, not by value, so modifications will propagate back\n// to the original data. Such modifications are only allowed for ``mutable``\n// references, not ``readonly``.\ndef copy_3_bytes(readonly array[uint[8], 3] in_array, mutable array[uint[8], 3] out_array) {\n // Within this block, ``in_array`` can be read from, but not written to,\n // whereas ``out_array`` can be both read from and written to.\n}\n\n// When specifying array subroutine parameters, there is a second format where\n// the sizes of the dimensions are not given explicitly, only the number of\n// dimensions. This is where the ``sizeof`` operator is most useful. In these\n// cases, `sizeof` is _not_ a compile-time constant.\ndef multi_dimensional_input(readonly array[int[32], #dim=3] my_array) {\n uint[32] dimension_0 = sizeof(my_array, 0);\n uint[32] dimension_1 = sizeof(my_array, 1);\n uint[32] dimension_2 = sizeof(my_array, 2);\n}\n",
|
||||
"expect": {
|
||||
"refused": "Q107"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/cphase.qasm",
|
||||
"qasm": "gate cphase(θ) a, b\n{\n U(0, 0, θ / 2) a;\n CX a, b;\n U(0, 0, -θ / 2) b;\n CX a, b;\n U(0, 0, θ / 2) b;\n}\ncphase(π / 2) q[0], q[1];\n",
|
||||
"expect": {
|
||||
"refused": "Q102"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/dd.qasm",
|
||||
"qasm": "/* CPMG XY4 decoupling w/ boxing\n * This example demonstrates the use of referential delays\n * and time alignment.\n*/\ninclude \"stdgates.inc\";\n\nstretch a;\nduration start_stretch = -0.5 * durationof({x $0;}) + a;\nduration middle_stretch = -0.5 * durationof({x $0;}) - 5 * durationof({y $0;}) + a;\nduration end_stretch = -0.5 * durationof({y $0;}) + a;\n\nbox {\n delay[start_stretch] $0;\n x $0;\n delay[middle_stretch] $0;\n y $0;\n delay[middle_stretch] $0;\n x $0;\n delay[middle_stretch] $0;\n y $0;\n delay[end_stretch] $0;\n\n cx $2, $3;\n cx $1, $2;\n u $3;\n}\n",
|
||||
"expect": {
|
||||
"refused": "Q405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/defcal.qasm",
|
||||
"qasm": "defcalgrammar \"openpulse\";\n\ndefcal x $0 {\n play drive($0), gaussian(...);\n}\n\ndefcal x $1 {\n play drive($1), gaussian(...);\n}\n\ndefcal rz(angle[20] theta) q {\n shift_phase drive(q), -theta;\n}\n\ndefcal measure $0 -> bit {\n complex[int[24]] iq;\n bit state;\n complex[int[12]] k0[1024] = [i0 + q0*j, i1 + q1*j, i2 + q2*j, ...];\n play measure($0), flat_top_gaussian(...);\n iq = capture acquire($0), 2048, extern(k0);\n return threshold(iq, 1234);\n}\n\ndefcal zx90_ix $0, $1 {\n play drive($0, \"cr1\"), flat_top_gaussian(...); // uses a non-default\n // frame labeled \"cr1\"\n}\n\ndefcal cx $0, $1 {\n zx90_ix $0, $1;\n x $0;\n shift_phase drive($0, \"cr1\");\n zx90_ix $0, $1;\n x $0;\n x $1;\n}\n",
|
||||
"expect": {
|
||||
"refused": "Q100"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/gateteleport.qasm",
|
||||
"qasm": "// Repetition code gate teleportation\ninclude \"stdgates.inc\";\n\n// declarations\nconst int[32] n = 3;\nextern vote(bit[n]) -> bit;\n\ndef logical_meas(qubit[3] d) -> bit {\n bit[3] c;\n bit r;\n measure d -> c;\n r = vote(c);\n return r;\n}\n\nqubit[3] q;\nqubit[3] a;\nbit r;\n\n// prep magic state\nrz(pi/4) a;\n\n// entangle two logical registers\ncx q, a;\n\n// measure out the ancilla\nr = logical_meas(a);\n\n// if we get a logical |1> then we need to apply a logical Z correction\nif (r == 1) z q;\n",
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/inverseqft1.qasm",
|
||||
"qasm": "// QFT and measure, version 1\ninclude \"stdgates.inc\";\n\nqubit[4] q;\nbit[4] c;\nreset q;\nh q;\nbarrier q;\nh q[0];\nc[0] = measure q[0];\nif(int[4](c) == 1) { rz(pi / 2) q[1]; }\nh q[1];\nc[1] = measure q[1];\nif(int[4](c) == 1){ rz(pi / 4) q[2]; }\nif(int[4](c) == 2){ rz(pi / 2) q[2]; }\nif(int[4](c) == 3){ rz(pi / 2 + pi / 4) q[2]; }\nh q[2];\nc[2] = measure q[2];\nif(int[4](c) == 1) rz(pi / 8) q[3];\nif(int[4](c) == 2) rz(pi / 4) q[3];\nif(int[4](c) == 3) rz(pi/4+pi/8) q[3];\nif(int[4](c) == 4) rz(pi / 2) q[3];\nif(int[4](c) == 5) rz(pi / 2 + pi / 8) q[3];\nif(int[4](c) == 6) rz(pi / 2+ pi / 4) q[3];\nif(int[4](c) == 7) rz(pi / 2 + pi / 4 + pi / 8) q[3];\nh q[3];\nc[3] = measure q[3];\n",
|
||||
"expect": {
|
||||
"deterministic": "0000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/inverseqft2.qasm",
|
||||
"qasm": "// QFT and measure, version 2\ninclude \"stdgates.inc\";\n\nqubit[4] q;\nbit c0;\nbit c1;\nbit c2;\nbit c3;\n\nreset q;\nh q;\nbarrier q;\nh q[0];\nmeasure q[0] -> c0;\nif(c0 == 1) { rz(pi / 2) q[1]; }\nh q[1];\nmeasure q[1] -> c1;\nif(c0==1) { rz(pi / 4) q[2]; }\nif(c1==1) { rz(pi / 2) q[2]; }\nh q[2];\nmeasure q[2] -> c2;\nif(c0 == 1) { rz(pi / 8) q[3]; }\nif(c1 == 1) { rz(pi / 4) q[3]; }\nif(c2 == 1) { rz(pi / 2) q[3]; }\nh q[3];\nmeasure q[3] -> c3;\n",
|
||||
"expect": {
|
||||
"deterministic": "0000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/ipe.qasm",
|
||||
"qasm": "/*\n * Iterative phase estimation\n */\ninclude \"stdgates.inc\";\n\nconst int[32] n = 10; // number of iterations\nconst float[32] theta = 3 * pi / 8; // phase angle on target qubit\n\nqubit q; // phase estimation qubit\nqubit r; // target qubit for the controlled-unitary gate\nangle[n] c; // phase estimation bits\n\n// initialize\nreset q;\nreset r;\n\n// prepare uniform superposition of eigenvectors of phase\nh r;\n\n// iterative phase estimation loop\nuint[n] power = 1;\nfor uint i in [0: n - 1] { // implicitly cast val to int\n reset q;\n h q;\n ctrl @ pow(power) @ phase(theta) q, r;\n inv @ phase(c) q;\n h q;\n measure q -> c[0];\n // newest measurement outcome is associated to a pi/2 phase shift\n // in the next iteration, so shift all bits of c left\n c <<= 1;\n power <<= 1;\n}\n\n// Now c contains the n-bit estimate of phi in the\n// eigenvalue e^{i*phi} and qreg r is projected to an\n// approximate eigenstate of the phase gate.\n",
|
||||
"expect": {
|
||||
"refused": "Q128"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/msd.qasm",
|
||||
"qasm": "/*\n * Magic state distillation and computation\n */\ninclude \"stdgates.inc\";\n\nconst int[32] buffer_size = 6; // size of magic state buffer\n\n// Y-basis measurement\ndef ymeasure(qubit q) -> bit {\n s q;\n h q;\n return measure q;\n}\n\n/*\n * Distillation subroutine takes 10 |H> magic states\n * and 3 scratch qubits that will be reinitialized.\n * The first two input magic states are the outputs.\n * The subroutine returns a success bit that is true\n * on success and false otherwise (see arXiv:1811.00566).\n */\ndef distill(qubit[10] magic, qubit[3] scratch) -> bool {\n bit temp;\n bit[3] checks;\n // Encode two magic states in the [[4,2,2]] code\n reset scratch[0: 1];\n h scratch[1];\n cx scratch[1], magic[0];\n cx magic[1], scratch[0];\n cx magic[0], scratch[0];\n cx scratch[1], magic[1];\n // Body of distillation circuit\n cy magic[2], scratch[0];\n h magic[1];\n temp = ymeasure(magic[2]);\n if(temp == 1) { ry(-pi / 2) scratch[0]; }\n reset scratch[2];\n h scratch[2];\n cz scratch[2], scratch[0];\n cy magic[3], scratch[0];\n temp = ymeasure(magic[3]);\n if(temp==0) { ry(pi / 2) scratch[0]; }\n h scratch[0];\n s scratch[0];\n cy magic[4], scratch[1];\n temp = ymeasure(magic[4]);\n if(temp==1) { ry(-pi / 2) scratch[1]; }\n cz scratch[3], scratch[2];\n cy magic[5], scratch[1];\n temp = ymeasure(magic[5]);\n if(temp==0) { ry(pi / 2) scratch[1]; }\n cy scratch[0], magic[1];\n inv @ s scratch[1];\n cz scratch[0], scratch[1];\n h scratch[0];\n cy scratch[1], magic[1];\n cy magic[6], scratch[0];\n temp = ymeasure(magic[6]);\n if(temp == 1) { ry(-pi / 2) scratch[0]; }\n cz scratch[2], scratch[1];\n cz scratch[2], scratch[0];\n cy magic[7], scratch[0];\n temp = ymeasure(magic[7]);\n if(temp == 0) ry(pi / 2) scratch[0];\n cy magic[8], scratch[1];\n temp = ymeasure(magic[8]);\n if(temp==1) { ry(-pi / 2) scratch[1]; }\n cz scratch[2], scratch[1];\n cy magic[9], scratch[1];\n temp = ymeasure(magic[9]);\n if(temp == 0) { ry(pi / 2) scratch[1]; }\n h scratch[2];\n // Decode [[4,2,2]] code\n cx magic[0], scratch[0];\n cx scratch[1], magic[1];\n cx magic[1], scratch[0];\n cx scratch[1], magic[0];\n h scratch[1];\n checks = measure scratch;\n success = ~(bool(checks[0]) | bool(checks[1]) | bool(checks[2]));\n return success;\n}\n\n// Repeat level-0 distillation until success\ndef rus_level_0(qubit[10] magic, qubit[3] scratch) {\n bool success;\n while(~success) {\n reset magic;\n ry(pi / 4) magic;\n success = distill(magic, scratch);\n }\n}\n\n/*\n * Run two levels of 10:2 magic state distillation.\n * Both levels have two distillations running in parallel.\n * The output pairs from the first level are separated and\n * input to different second levels distillation circuits\n * because a failure in a first level circuit can lead to\n * errors on both outputs.\n * Put the requested even number of copies into the buffer.\n */\ndef distill_and_buffer(int[32] num, qubit[33] work, qubit[buffer_size] buffer) {\n int[32] index;\n bit success_0;\n bit success_1;\n let magic_lvl0 = work[0: 9];\n let magic_lvl1_0 = work[10: 19];\n let magic_lvl1_1 = work[20: 29];\n let scratch = work[30: 32];\n\n // Run first-level circuits until 10 successes,\n // storing the outputs for use in the second level\n for uint i in [0: 9] {\n rus_level_0 magic_lvl0, scratch;\n swap magic_lvl0[0], magic_lvl1_0[i];\n swap magic_lvl0[1], magic_lvl1_1[i];\n }\n\n // Run two second level circuits simultaneously\n success_0 = distill(magic_lvl1_0, scratch);\n success_1 = distill(magic_lvl1_1, scratch);\n\n // Move usable magic states into the buffer register\n if(success_0 && index < buffer_size) {\n swap magic_lvl1_0[0: 1], buffer[index: index + 1];\n index += 2;\n }\n if(success_1 && index < buffer_size) {\n swap magic_lvl1_1[0: 1], buffer[index: index + 1];\n index += 2;\n }\n}\n\n// Apply Ry(pi/4) to a qubit by consuming a magic state\n// from the magic state buffer at address \"addr\"\ndef Ty(int[32] addr, qubit q, qubit[buffer_size] buffer) {\n bit outcome;\n cy buffer[addr], q;\n outcome = ymeasure(buffer[addr]);\n if(outcome == 1) ry(pi / 2) q;\n}\n\nqubit[33] workspace;\nqubit[buffer_size] buffer;\n\nqubit[5] q;\nbit[5] c;\nint[32] address;\n\n// initialize\nreset workspace;\nreset buffer;\nreset q;\n\ndistill_and_buffer(buffer_size) workspace, buffer;\n\n// Consume magic states to apply some gates ...\nh q[0];\ncx q[0], q[1];\nTy(address) q[0], buffer;\naddress += 1;\ncx q[0], q[1];\nTy(address) q[1], buffer;\naddress += 1;\n\n// In principle each Ty gate can execute as soon as the magic\n// state is available at the address in the buffer register.\n\n// We can continue alternating state distillation and computation\n// to refill and empty a circular buffer.\n",
|
||||
"expect": {
|
||||
"refused": "Q107"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/qec.qasm",
|
||||
"qasm": "// Repetition code syndrome measurement\ninclude \"stdgates.inc\";\n\nqubit[3] q;\nqubit[2] a;\nbit[3] c;\nbit[2] syn;\n\ndef syndrome(qubit[3] d, qubit[2] a) -> bit[2] {\n bit[2] b;\n cx d[0], a[0];\n cx d[1], a[0];\n cx d[1], a[1];\n cx d[2], a[1];\n measure a -> b;\n return b;\n}\nreset q;\nreset a;\nx q[0]; // insert an error\nbarrier q;\nsyn = syndrome(q, a);\nif(int[2](syn)==1) x q[0];\nif(int[2](syn)==2) x q[2];\nif(int[2](syn)==3) x q[1];\nc = measure q;\n",
|
||||
"expect": {
|
||||
"deterministic": "01000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/qft.qasm",
|
||||
"qasm": "// quantum Fourier transform\ninclude \"stdgates.inc\";\nqubit[4] q;\nbit[4] c;\nreset q;\nx q[0];\nx q[2];\nbarrier q;\nh q[0];\ncphase(pi / 2) q[1], q[0];\nh q[1];\ncphase(pi / 4) q[2], q[0];\ncphase(pi / 2) q[2], q[1];\nh q[2];\ncphase(pi / 8) q[3], q[0];\ncphase(pi / 4) q[3], q[1];\ncphase(pi / 2) q[3], q[2];\nh q[3];\nc = measure q;\n",
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"0000": 0.0625,
|
||||
"0001": 0.0625,
|
||||
"0010": 0.0625,
|
||||
"0011": 0.0625,
|
||||
"0100": 0.0625,
|
||||
"0101": 0.0625,
|
||||
"0110": 0.0625,
|
||||
"0111": 0.0625,
|
||||
"1000": 0.0625,
|
||||
"1001": 0.0625,
|
||||
"1010": 0.0625,
|
||||
"1011": 0.0625,
|
||||
"1100": 0.0625,
|
||||
"1101": 0.0625,
|
||||
"1110": 0.0625,
|
||||
"1111": 0.0625
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/qpt.qasm",
|
||||
"qasm": "include \"stdgates.inc\";\n\ngate pre q { } // pre-rotation\ngate post q { } // post-rotation\n\nqubit q;\nbit c;\nreset q;\npre q;\nbarrier q;\nh q;\nbarrier q;\npost q;\nc = measure q;\n",
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"0": 0.5,
|
||||
"1": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/rb.qasm",
|
||||
"qasm": "// One randomized benchmarking sequence\ninclude \"stdgates.inc\";\n\nqubit[2] q;\nbit[2] c;\n\nreset q;\nh q[0];\nbarrier q;\ncz q[0], q[1];\nbarrier q;\ns q[0];\ncz q[0], q[1];\nbarrier q;\ns q[0];\nz q[0];\nh q[0];\nbarrier q;\nmeasure q -> c;\n",
|
||||
"expect": {
|
||||
"deterministic": "00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/rus.qasm",
|
||||
"qasm": "/*\n * Repeat-until-success circuit for Rz(theta),\n * cos(theta-pi)=3/5, from Nielsen and Chuang, Chapter 4.\n */\ninclude \"stdgates.inc\";\n\n/*\n * Applies identity if out is 01, 10, or 11 and a Z-rotation by\n * theta + pi where cos(theta)=3/5 if out is 00.\n * The 00 outcome occurs with probability 5/8.\n */\ndef segment(qubit[2] anc, qubit psi) -> bit[2] {\n bit[2] b;\n reset anc;\n h anc;\n ccx anc[0], anc[1], psi;\n s psi;\n ccx anc[0], anc[1], psi;\n z psi;\n h anc;\n measure anc -> b;\n return b;\n}\n\nqubit input_qubit;\nqubit[2] ancilla;\nbit[2] flags = \"11\";\nbit output_qubit;\n\nreset input_qubit;\nh input_qubit;\n\n// braces are optional in this case\nwhile(int[2](flags) != 0) {\n flags = segment(ancilla, input_qubit);\n}\nrz(pi - arccos(3 / 5)) input_qubit;\nh input_qubit;\noutput_qubit = measure input_qubit; // should get zero\n",
|
||||
"expect": {
|
||||
"refused": "Q310"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/scqec.qasm",
|
||||
"qasm": "/*\n * Surface code quantum memory.\n *\n * Estimate the failure probability as a function\n * of parameters at the top of the file.\n */\ninclude \"stdgates.inc\";\n\nconst int[32] d = 3; // code distance\nconst int[32] m = 10; // number of syndrome measurement cycles\nconst int[32] shots = 1000; // number of samples\nconst int[32] n = d**2; // number of code qubits\n\nuint[32] failures; // number of observed failures\n\nextern zfirst(creg[n - 1], int[32], int[32]);\nextern send(creg[n -1 ], int[32], int[32], int[32]);\nextern zlast(creg[n], int[32], int[32]) -> bit;\n\nqubit[n] data; // code qubits\nqubit[n-1] ancilla; // syndrome qubits\n/*\n * Ancilla are addressed in a (d-1) by (d-1) square array\n * followed by 4 length (d-1)/2 arrays for the top,\n * bottom, left, and right boundaries.\n */\n\nbit[n-1] layer; // syndrome outcomes in a cycle\nbit[n] data_outcomes; // data outcomes at the end\nbit outcome; // logical outcome\n\n/* Declare a sub-circuit for Hadamard gates on ancillas\n */\ndef hadamard_layer(qubit[n-1] ancilla) {\n // Hadamards in the bulk\n for uint[32] row in [0: d-2] {\n for uint[32] col in [0: d-2] {\n bit[32] sum = bit[32](row + col);\n if(sum[0] == 1)\n h ancilla[row * (d - 1) + col];\n }\n }\n // Hadamards on the left and right boundaries\n for uint[32] i in [0: d - 2] {\n h ancilla[(d - 1)**2 + (d - 1) + i];\n }\n}\n\n/* Declare a sub-circuit for a syndrome cycle.\n */\ndef cycle(qubit[n] data, qubit[n-1] ancilla) -> bit[n-1] {\n reset ancilla;\n hadamard_layer ancilla;\n\n // First round of CNOTs in the bulk\n for uint[32] row in [0: d - 2] {\n for uint[32] col in [0:d - 2] {\n bit[32] sum = bit[32](row + col);\n if(sum[0] == 0)\n cx data[row * d + col], ancilla[row * (d - 1) + col];\n if(sum[0] == 1) {\n cx ancilla[row * (d - 1) + col], data[row * d + col];\n }\n }\n }\n // First round of CNOTs on the bottom boundary\n for uint[32] i in [0: (d - 3) / 2] {\n cx data[d * (d - 1) + 2 * i], ancilla[(d - 1) ** 2 + ( d- 1) / 2 + i];\n }\n // First round of CNOTs on the right boundary\n for uint[32] i in [0: (d - 3) / 2] {\n cx ancilla[(d - 1) ** 2 + 3 * (d - 1) / 2 + i], data[2 * d - 1 + 2 * d * i];\n }\n // Remaining rounds of CNOTs, go here ...\n\n hadamard_layer ancilla;\n return measure ancilla;\n}\n\n// Loop over shots\nfor uint[32] shot in [1: shots] {\n\n // Initialize\n reset data;\n layer = cycle(data, ancilla);\n zfirst(layer, shot, d);\n\n // m cycles of syndrome measurement\n for int[32] i in [1: m] {\n layer = cycle(data, ancilla);\n send(layer, shot, i, d);\n }\n\n // Measure\n data_outcomes = measure data;\n\n outcome = zlast(data_outcomes, shot, d);\n failures += int[1](outcome);\n}\n\n/* The ratio of \"failures\" to \"shots\" is our result.\n * The data can be logged by the external functions too.\n */\n",
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/t1.qasm",
|
||||
"qasm": "/* Measuring the relaxation time of a qubit\n * This example demonstrates the repeated use of fixed delays.\n*/\ninclude \"stdgates.inc\";\n\nduration stride = 1us; // time resolution of points taken\nconst int[32] points = 50; // number of points taken\nconst int[32] shots = 1000; // how many shots per point\n\nint[32] counts0;\nint[32] counts1 = 0; // surviving |1> populations of qubits\n\nextern tabulate(int[32], int[32], int[32]);\n\nbit c0;\nbit c1;\n\ndefcalgrammar \"openpulse\";\n\n// define a gate calibration for an X gate on any qubit\ndefcal x q {\n play drive(q), gaussian(100, 30, 5);\n}\n\nfor int[32] p in [0 : points-1] {\n for uint i in [1 : shots] {\n // start of a basic block\n reset $0;\n reset $1;\n // excite qubits\n x $0;\n x $1;\n // wait for a fixed time indicated by loop counter\n delay[p * stride] $0;\n // wait for a fixed time indicated by loop counters\n delay[p * durationof({x $1;})];\n // read out qubit states\n c0 = measure $0;\n c1 = measure $1;\n // increment counts memories, if a 1 is seen\n counts0 += int[1](c0);\n counts1 += int[1](c1);\n }\n // log survival probability curve\n tabulate(counts0, shots, p);\n tabulate(counts1, shots, p);\n}\n",
|
||||
"expect": {
|
||||
"refused": "Q405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/teleport.qasm",
|
||||
"qasm": "// quantum teleportation example\nOPENQASM 3; // Version statement is optional\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit c0;\nbit c1;\nbit c2;\n// optional post-rotation for state tomography\n// empty gate body => identity gate\ngate post q { }\nreset q;\nU(0.3, 0.2, 0.1) q[0];\nh q[1];\ncx q[1], q[2];\nbarrier q;\ncx q[0], q[1];\nh q[0];\nc0 = measure q[0];\nc1 = measure q[1];\nif(c0==1) z q[2];\nif(c1==1) { x q[2]; } // braces optional in this case\npost q[2];\nc2 = measure q[2];\n",
|
||||
"expect": {
|
||||
"expectations": {
|
||||
"Z2": 0.955336489125606
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/varteleport.qasm",
|
||||
"qasm": "/*\n * Prepare a parameterized number of Bell pairs\n * and teleport a qubit using them.\n */\ninclude \"stdgates.inc\";\n\nconst int[32] n_pairs = 10; // number of teleportations to do\n\ndef bellprep(qubit[2] q) {\n reset q;\n h q[0];\n cx q[0], q[1];\n}\n\ndef xprepare(qubit q) {\n reset q;\n h q;\n}\n\nqubit input_qubit;\nbit output_qubit;\nqubit[2*n_pairs] q;\n\nxprepare(input_qubit);\nrz(pi / 4) input_qubit;\n\nlet io = input_qubit;\nfor uint i in [0: n_pairs - 1] {\n let bp = q[{2*i, 2*i + 1}];\n bit[2] pf;\n bellprep bp;\n cx io, bp[0];\n h io;\n pf[0] = measure io;\n pf[1] = measure bp[0];\n if (pf[0]==1) z bp[1];\n if (pf[1]==1) x bp[1];\n let io = bp[1];\n}\n\nh io;\noutput_qubit = measure io; // should get zero\n",
|
||||
"expect": {
|
||||
"refused": "Q101"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/vqe.qasm",
|
||||
"qasm": "/*\n * Variational eigensolver example\n *\n * Goal is to estimate the energy for a fixed set of parameters.\n * The parameters are updated outside of this program and a new\n * OpenQASM circuit is generated for the next iteration.\n */\ninclude \"stdgates.inc\";\n\nconst int[32] n = 10; // number of qubits\nconst int[32] layers = 3; // number of entangler layers\nconst int[32] prec = 16; // precision of all types\nconst int[32] shots = 1000; // number of shots per Pauli observable\n\n// Parameters could be written to local variables for this\n// iteration, but we will request them using extern functions\nextern get_parameter(uint[prec]) -> angle[prec];\nextern get_npaulis() -> uint[prec];\nextern get_pauli(int[prec]) -> bit[2 * n];\n\n// The energy calculation uses floating point division,\n// so we do that calculation in an extern function\nextern update_energy(int[prec], uint[prec], float[prec]) -> float[prec];\n\ngate entangler q { for uint i in [0:n-2] { cx q[i], q[i+1]; } }\ndef xmeasure(qubit q) -> bit { h q; return measure q; }\ndef ymeasure(qubit q) -> bit { s q; h q; return measure q; }\n\n/* Pauli measurement circuit.\n * The first n-bits of spec are the X component.\n * The second n-bits of spec are the Z component.\n */\ndef pauli_measurement(bit[2*n] spec, qubit[n] q) -> bit {\n bit b = 0;\n for uint[prec] i in [0: n - 1] {\n bit temp;\n if(spec[i]==1 && spec[n+i]==0) { temp = xmeasure(q[i]); }\n if(spec[i]==0 && spec[n+i]==1) { temp = measure q[i]; }\n if(spec[i]==1 && spec[n+i]==1) { temp = ymeasure(q[i]); }\n b ^= temp;\n }\n return b;\n}\n\n// Circuit to prepare trial wave function\ndef trial_circuit(qubit[n] q) {\n for int[prec] l in [0: layers - 1] {\n for uint[prec] i in [0: n - 1] {\n angle[prec] theta;\n theta = get_parameter(l * layers + i);\n ry(theta) q[i];\n }\n if(l != layers - 1) entangler q;\n }\n}\n\n/* Apply VQE ansatz circuit and measure a Pauli operator\n * given by spec. Return the number of 1 outcomes.\n */\ndef counts_for_term(bit[2*n] spec, qubit[n] q) -> uint[prec] {\n uint[prec] counts;\n for uint i in [1: shots] {\n bit b;\n reset q;\n trial_circuit q;\n b = pauli_measurement(spec, q);\n counts += int[1](b);\n }\n return counts;\n}\n\n// Estimate the expected energy\ndef estimate_energy(qubit[n] q) -> float[prec] {\n float[prec] energy;\n uint[prec] npaulis = get_npaulis();\n for int[prec] t in [0:npaulis-1] {\n bit[2*n] spec = get_pauli(t);\n uint[prec] counts;\n counts = counts_for_term(spec, q);\n energy = update_energy(t, counts, energy);\n }\n return energy;\n}\n\nqubit[n] q;\nfloat[prec] energy;\n\nenergy = estimate_energy(q);\n",
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/def.qasm",
|
||||
"qasm": "OPENQASM 3.1;\ninclude \"stdgates.inc\";\n// Subroutines inlined: qubits by reference, classical arguments by value,\n// values returned.\nqubit[3] q;\ndef layer(qubit a, qubit b, float[64] t) { h a; cx a, b; rz(t) b; }\ndef half(float[64] x) -> float[64] { return x / 2; }\ndef twice(int[32] k) -> int[32] { return 2 * k; }\nlayer(q[0], q[1], half(pi / 2));\nlayer(q[1], q[2], pi / twice(4));\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/def.ref.qasm",
|
||||
"exact": "ok"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[3] q;\nh q[0];\ncx q[0], q[1];\nrz(pi / 4) q[1];\nh q[1];\ncx q[1], q[2];\nrz(pi / 8) q[2];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/def_measure.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Teleportation as a subroutine with bits of its own, fed forward, and a\n// subroutine whose returned measurement lands in the caller's bit.\nqubit[3] q;\nbit[1] r;\ndef teleport(qubit src, qubit mid, qubit dst) {\n bit a;\n bit b;\n h mid;\n cx mid, dst;\n cx src, mid;\n h src;\n a = measure src;\n b = measure mid;\n if (b) x dst;\n if (a) z dst;\n}\ndef read_out(qubit s) -> bit { return measure s; }\nx q[0];\nteleport(q[0], q[1], q[2]);\nr[0] = read_out(q[2]);\n",
|
||||
"expect": {
|
||||
"deterministic": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/inv.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\ngate g(a) x, y { h x; cx x, y; rz(a) y; s x; }\nh q[0];\nt q[1];\ninv @ g(0.3) q[0], q[1];\ninv @ sx q[1];\ninv @ U(0.1, 0.2, 0.3) q[0];\ninv @ iswap q[0], q[1];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/inv.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q[0];\nt q[1];\n// g's gates inverted, in reverse order\nsdg q[0];\nrz(-0.3) q[1];\ncx q[0], q[1];\nh q[0];\n// sx = h s h\nh q[1];\nsdg q[1];\nh q[1];\n// U(θ, φ, λ) is rz(φ) ry(θ) rz(λ) up to a phase\nrz(-0.2) q[0];\nry(-0.1) q[0];\nrz(-0.3) q[0];\n// iswap = s, s, h, cx, cx, h\nh q[1];\ncx q[1], q[0];\ncx q[0], q[1];\nh q[0];\nsdg q[1];\nsdg q[0];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/pow.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\ngate g a, b { h a; cx a, b; t b; }\npow(3) @ g q[0], q[1];\npow(-2) @ rx(0.4) q[0];\npow(4) @ t q[1];\npow(0) @ h q[0];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/pow.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q[0]; cx q[0], q[1]; t q[1];\nh q[0]; cx q[0], q[1]; t q[1];\nh q[0]; cx q[0], q[1]; t q[1];\nrx(-0.8) q[0];\nz q[1];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/root.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q[0];\nh q[1];\npow(0.5) @ x q[0];\npow(0.5) @ z q[1];\npow(0.5) @ s q[0];\npow(0.25) @ rz(1.2) q[1];\npow(-0.5) @ x q[1];\npow(0.5) @ cz q[0], q[1];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/root.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q[0];\nh q[1];\nsx q[0];\ns q[1];\nt q[0];\nrz(0.3) q[1];\nsxdg q[1];\ncp(pi / 2) q[0], q[1];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/ctrl_any.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Controls on any gate: a rotation under two controls, and a negative control.\nqubit[3] q;\nx q[0];\nx q[1];\nctrl(2) @ ry(pi / 3) q[0], q[1], q[2];\nnegctrl @ x q[2], q[0];\n",
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"010": 0.75,
|
||||
"111": 0.25
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/ctrl_user.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\ngate g a { h a; t a; }\nh q[0];\nctrl @ g q[0], q[1];\nctrl @ rz(0.7) q[1], q[0];\nctrl @ U(0.1, 0.2, 0.3) q[0], q[1];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/ctrl_user.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q[0];\nch q[0], q[1];\ncp(pi / 4) q[0], q[1];\ncrz(0.7) q[1], q[0];\ncu(0.1, 0.2, 0.3, 0) q[0], q[1];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/types.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Classical types, arithmetic, casts and built-in functions, folded on reading.\nqubit q;\nconst float[64] half = 0.5;\nangle[3] quarter = pi / 2;\ncomplex[float[64]] z = 1.0 + 2.0im;\nuint[8] u = 250;\nu += 3;\nint[8] k = int[8](-3.7);\nconst bit[4] mask = \"1010\";\narray[int[32], 3] a = {1, 2, 3};\nrx(half * pi) q;\nrz(quarter) q;\nry(real(z * z)) q;\nrz(float(u) / 1000) q;\nrx(k) q;\nry(popcount(mask) + a[2]) q;\nrz(sqrt(4.0) + arctan(1.0) * 4 - pi) q;\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/types.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit q;\nrx(pi / 2) q;\nrz(pi / 2) q;\nry(-3.0) q;\nrz(0.253) q;\nrx(-3.0) q;\nry(5.0) q;\nrz(2.0) q;\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/angle_round.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// An angle[4] holds 4 bits of a turn: pi/3 is held as 3/16 of a turn.\nqubit q;\nangle[4] t = pi / 3;\nh q;\nrz(t) q;\n",
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q121"
|
||||
],
|
||||
"equivalent": "lang/angle_round.ref.qasm",
|
||||
"exact": "ok"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit q;\nh q;\nrz(3 * pi / 8) q;\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/while_static.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[4] q;\nint i = 0;\nwhile (i < 4) {\n h q[i];\n i += 1;\n}\nint j = 3;\nwhile (true) {\n if (j < 1) break;\n x q[j];\n j -= 2;\n}\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/while_static.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[4] q;\nh q[0];\nh q[1];\nh q[2];\nh q[3];\nx q[3];\nx q[1];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/while_rus.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Repeat until success on measured bits, under a declared bound.\nqubit q;\nbit c;\nc = measure q;\[email protected]_iterations 3\nwhile (c == 0) {\n x q;\n c = measure q;\n}\n",
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q311"
|
||||
],
|
||||
"deterministic": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/while_unbounded.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\nbit c;\nc = measure q;\nwhile (c == 0) {\n x q;\n c = measure q;\n}\n",
|
||||
"expect": {
|
||||
"refused": "Q310"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/switch.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[3] q;\nbit[3] c;\nconst int mode = 2;\nswitch (mode) {\n case 1 { x q[0]; }\n case 2, 3 { x q[1]; }\n default { h q[0]; }\n}\nc[0] = measure q[1];\nc[1] = measure q[0];\nswitch (c[0:1]) {\n case 0 { }\n case 1 { x q[2]; }\n case 2 { h q[2]; }\n default { }\n}\nc[2] = measure q[2];\n",
|
||||
"expect": {
|
||||
"deterministic": "101"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/break_continue.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[8] q;\nfor int i in [0:7] {\n if (i == 2) continue;\n if (i == 5) break;\n x q[i];\n}\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/break_continue.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[8] q;\nx q[0];\nx q[1];\nx q[3];\nx q[4];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/runtime_break.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// `break` on a measured bit: a jump forward past the rest of the loop.\nqubit q;\nqubit[3] t;\nbit c;\nbit[3] r;\nfor int i in [0:2] {\n c = measure q;\n if (c) break;\n x t[i];\n x q;\n}\nr = measure t;\n",
|
||||
"expect": {
|
||||
"deterministic": "0011"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/conditions.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Comparisons, &&, || and ! on measured bits.\nqubit[3] p;\nqubit[3] t;\nbit[3] c;\nbit[3] r;\nx p[1];\nx p[2];\nc = measure p;\nif (c >= 6 && !c[0]) x t[0];\nif (c < 6 || c == 7) x t[1];\nif (c > 4 && c <= 6) x t[2];\nr = measure t;\n",
|
||||
"expect": {
|
||||
"deterministic": "101110"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/output.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\noutput bit[2] c;\noutput int[32] n = 3;\noutput float[64] t = pi / 4;\nx q[1];\nc = measure q;\n",
|
||||
"expect": {
|
||||
"deterministic": "10",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "c",
|
||||
"type": "bit[2]",
|
||||
"bits": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "n",
|
||||
"type": "int[32]",
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"name": "t",
|
||||
"type": "float[64]",
|
||||
"value": 0.7853981633974483
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/timing.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Durations carried, and labelled as not applied by the method.\nqubit[2] q;\nstretch s;\nduration d = 100ns;\nh q[0];\ndelay[2 * d] q[0];\nbox [1us] {\n cx q[0], q[1];\n}\ndelay[s] q[1];\nbarrier q;\nx[20ns] q[1];\n",
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q403"
|
||||
],
|
||||
"timing": true,
|
||||
"distribution": {
|
||||
"01": 0.5,
|
||||
"10": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/calibration.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// Calibrations kept verbatim for export, never run.\ndefcalgrammar \"openpulse\";\ncal {\n extern port d0;\n}\ndefcal x $0 {\n play(d0, gaussian(1.0, 160dt, 40dt));\n}\nqubit q;\nh q;\n",
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q450",
|
||||
"Q451",
|
||||
"Q452"
|
||||
],
|
||||
"calibrations": 3,
|
||||
"distribution": {
|
||||
"0": 0.5,
|
||||
"1": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/stdgates.qasm",
|
||||
"qasm": "OPENQASM 3.1;\ninclude \"stdgates.inc\";\n// Every standard gate, once, after a layer that leaves no symmetry.\nqubit[3] q;\nU(0.31, 0.72, -0.4) q[0];\nU(1.13, -0.25, 0.9) q[1];\nU(2.07, 0.5, 0.33) q[2];\nCX q[0], q[1];\nCX q[1], q[2];\nU(0.6, 1.1, -0.7) q[0];\nid q[0];\nx q[0];\ny q[1];\nz q[2];\nh q[0];\ns q[1];\nsdg q[2];\nt q[0];\ntdg q[1];\nsx q[2];\nsxdg q[0];\nrx(0.41) q[1];\nry(-1.3) q[2];\nrz(0.77) q[0];\np(1.9) q[1];\nphase(0.2) q[2];\nu1(-0.6) q[0];\nu2(0.3, -1.2) q[1];\nu3(0.8, 0.1, 2.2) q[2];\nU(1.4, -0.9, 0.35) q[0];\ncx q[0], q[1];\nCX q[2], q[0];\ncy q[1], q[2];\ncz q[2], q[0];\nch q[0], q[2];\ncp(0.9) q[1], q[0];\ncphase(-1.1) q[2], q[1];\ncrx(0.6) q[0], q[1];\ncry(-0.8) q[1], q[2];\ncrz(1.7) q[2], q[0];\ncu(0.5, 0.25, -0.75, 0.4) q[0], q[2];\nswap q[1], q[2];\niswap q[0], q[1];\nrxx(0.45) q[1], q[2];\nryy(-0.65) q[0], q[2];\nrzz(1.25) q[0], q[1];\nccx q[0], q[1], q[2];\nccz q[2], q[0], q[1];\ncswap q[1], q[2], q[0];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/stdgates.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\n// The same gates, each written in U and CX alone.\ngate d_x a { U(pi, 0, pi) a; }\ngate d_y a { U(pi, pi / 2, pi / 2) a; }\ngate d_z a { U(0, 0, pi) a; }\ngate d_h a { U(pi / 2, 0, pi) a; }\ngate d_s a { U(0, 0, pi / 2) a; }\ngate d_sdg a { U(0, 0, -pi / 2) a; }\ngate d_t a { U(0, 0, pi / 4) a; }\ngate d_tdg a { U(0, 0, -pi / 4) a; }\ngate d_p(l) a { U(0, 0, l) a; }\ngate d_rx(t) a { U(t, -pi / 2, pi / 2) a; }\ngate d_ry(t) a { U(t, 0, 0) a; }\ngate d_rz(t) a { U(0, 0, t) a; }\ngate d_sx a { d_h a; d_s a; d_h a; }\ngate d_sxdg a { d_h a; d_sdg a; d_h a; }\ngate d_cz a, b { d_h b; CX a, b; d_h b; }\ngate d_cy a, b { d_sdg b; CX a, b; d_s b; }\ngate d_ch a, b { d_h b; d_sdg b; CX a, b; d_h b; d_t b; CX a, b; d_t b; d_h b; d_s b; d_x b; d_s a; }\ngate d_cp(l) a, b { d_p(l / 2) a; CX a, b; d_p(-l / 2) b; CX a, b; d_p(l / 2) b; }\ngate d_crz(l) a, b { d_rz(l / 2) b; CX a, b; d_rz(-l / 2) b; CX a, b; }\ngate d_crx(l) a, b { d_p(pi / 2) b; CX a, b; U(-l / 2, 0, 0) b; CX a, b; U(l / 2, -pi / 2, 0) b; }\ngate d_cry(l) a, b { d_ry(l / 2) b; CX a, b; d_ry(-l / 2) b; CX a, b; }\ngate d_cu(t, f, l, g) a, b { d_p(g) a; d_p((l + f) / 2) a; d_p((l - f) / 2) b; CX a, b; U(-t / 2, 0, -(f + l) / 2) b; CX a, b; U(t / 2, f, 0) b; }\ngate d_swap a, b { CX a, b; CX b, a; CX a, b; }\ngate d_iswap a, b { d_s a; d_s b; d_h a; CX a, b; CX b, a; d_h b; }\ngate d_rzz(t) a, b { CX a, b; d_rz(t) b; CX a, b; }\ngate d_rxx(t) a, b { d_h a; d_h b; d_rzz(t) a, b; d_h a; d_h b; }\ngate d_ryy(t) a, b { d_rx(pi / 2) a; d_rx(pi / 2) b; d_rzz(t) a, b; d_rx(-pi / 2) a; d_rx(-pi / 2) b; }\ngate d_ccx a, b, c { d_h c; CX b, c; d_tdg c; CX a, c; d_t c; CX b, c; d_tdg c; CX a, c; d_t b; d_t c; d_h c; CX a, b; d_t a; d_tdg b; CX a, b; }\ngate d_ccz a, b, c { d_h c; d_ccx a, b, c; d_h c; }\ngate d_cswap a, b, c { CX c, b; d_ccx a, b, c; CX c, b; }\nqubit[3] q;\nU(0.31, 0.72, -0.4) q[0];\nU(1.13, -0.25, 0.9) q[1];\nU(2.07, 0.5, 0.33) q[2];\nCX q[0], q[1];\nCX q[1], q[2];\nU(0.6, 1.1, -0.7) q[0];\nd_x q[0];\nd_y q[1];\nd_z q[2];\nd_h q[0];\nd_s q[1];\nd_sdg q[2];\nd_t q[0];\nd_tdg q[1];\nd_sx q[2];\nd_sxdg q[0];\nd_rx(0.41) q[1];\nd_ry(-1.3) q[2];\nd_rz(0.77) q[0];\nd_p(1.9) q[1];\nd_p(0.2) q[2];\nd_p(-0.6) q[0];\nU(pi / 2, 0.3, -1.2) q[1];\nU(0.8, 0.1, 2.2) q[2];\nU(1.4, -0.9, 0.35) q[0];\nCX q[0], q[1];\nCX q[2], q[0];\nd_cy q[1], q[2];\nd_cz q[2], q[0];\nd_ch q[0], q[2];\nd_cp(0.9) q[1], q[0];\nd_cp(-1.1) q[2], q[1];\nd_crx(0.6) q[0], q[1];\nd_cry(-0.8) q[1], q[2];\nd_crz(1.7) q[2], q[0];\nd_cu(0.5, 0.25, -0.75, 0.4) q[0], q[2];\nd_swap q[1], q[2];\nd_iswap q[0], q[1];\nd_rxx(0.45) q[1], q[2];\nd_ryy(-0.65) q[0], q[2];\nd_rzz(1.25) q[0], q[1];\nd_ccx q[0], q[1], q[2];\nd_ccz q[2], q[0], q[1];\nd_cswap q[1], q[2], q[0];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/aliases.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[6] q;\nqubit r;\nlet evens = q[0:2:5];\nlet tail = q[-2:] ++ r;\nh evens;\nx tail;\ncx q[{1, 3}], q[{2, 4}];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/aliases.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[6] q;\nqubit r;\nh q[0];\nh q[2];\nh q[4];\nx q[4];\nx q[5];\nx r;\ncx q[1], q[2];\ncx q[3], q[4];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/physical.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nh $0;\ncx $0, $1;\nrz(0.2) $2;\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/physical.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[3] q;\nh q[0];\ncx q[0], q[1];\nrz(0.2) q[2];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/gphase.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q;\ngphase(0.3);\nctrl @ gphase(0.7) q[0];\nnegctrl @ gphase(0.2) q[1];\n",
|
||||
"expect": {
|
||||
"equivalent": "lang/gphase.ref.qasm"
|
||||
},
|
||||
"reference_qasm": "OPENQASM 3.1;\nqubit[2] q;\nh q;\np(0.7) q[0];\nx q[1];\np(0.2) q[1];\nx q[1];\n"
|
||||
},
|
||||
{
|
||||
"file": "lang/bits_known.qasm",
|
||||
"qasm": "OPENQASM 3.1;\n// A bit register set by a constant is known until a measurement writes it.\nqubit[2] q;\nbit[2] b = \"10\";\nif (b == 2) x q[0];\nif (b[0]) x q[1];\nb = measure q;\n",
|
||||
"expect": {
|
||||
"deterministic": "01"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/generator.qasm",
|
||||
"qasm": "OPENQASM 3.1;\ninput uint n;\nqubit[n] q;\nh q[0];\nfor uint i in [0:n-2] {\n cx q[i], q[i + 1];\n}\n",
|
||||
"expect": {
|
||||
"inputs": {
|
||||
"n": 4
|
||||
},
|
||||
"distribution": {
|
||||
"0000": 0.5,
|
||||
"1111": 0.5
|
||||
},
|
||||
"exact": "ok"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/qasm2.qasm",
|
||||
"qasm": "OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\ncreg c[2];\nu3(pi, 0, pi) q[0];\nu2(0, pi) q[1];\nu1(pi/2) q[1];\nCX q[0], q[1];\nmeasure q -> c;\n",
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"01": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/qasm2_if.qasm",
|
||||
"qasm": "OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\ncreg c[2];\nx q[0];\nmeasure q -> c;\nif(c==1) x q[1];\nmeasure q[1] -> c[1];\n",
|
||||
"expect": {
|
||||
"deterministic": "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/exported.qasm",
|
||||
"qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\ngate rzx(_gate_p_0) _gate_q_0, _gate_q_1 {\n h _gate_q_1;\n cx _gate_q_0, _gate_q_1;\n rz(_gate_p_0) _gate_q_1;\n cx _gate_q_0, _gate_q_1;\n h _gate_q_1;\n}\nbit[3] c;\nqubit[3] q;\nh q[0];\ncx q[0], q[1];\nrzx(1.5707963267948966) q[1], q[2];\nrzx(-1.5707963267948966) q[1], q[2];\ncx q[1], q[2];\nc[0] = measure q[0];\nc[1] = measure q[1];\nc[2] = measure q[2];\n",
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"000": 0.5,
|
||||
"111": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_root.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\npow(0.5) @ U(0.1, 0.2, 0.3) q;\n",
|
||||
"expect": {
|
||||
"refused": "Q205"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_extern.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nextern f(int) -> int;\nqubit q;\nrz(f(1)) q;\n",
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_runtime.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\nbit c;\nc = measure q;\nint k = c;\n",
|
||||
"expect": {
|
||||
"refused": "Q306"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_durationof.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\nduration d = durationof({ x q; });\n",
|
||||
"expect": {
|
||||
"refused": "Q405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_opaque.qasm",
|
||||
"qasm": "OPENQASM 2.0;\nqreg q[1];\nopaque g a;\ng q[0];\n",
|
||||
"expect": {
|
||||
"refused": "Q126"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_truncating.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\nrz(1/2) q;\n",
|
||||
"expect": {
|
||||
"refused": "Q118"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_caret.qasm",
|
||||
"qasm": "qubit q;\nrz(2 ^ 3) q;\n",
|
||||
"expect": {
|
||||
"refused": "Q119"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_unknown_gate.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\nfoo q;\n",
|
||||
"expect": {
|
||||
"refused": "Q103"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/exact_not_dyadic.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit q;\nh q;\nrz(pi / 3) q;\n",
|
||||
"expect": {
|
||||
"exact": "Q500",
|
||||
"distribution": {
|
||||
"0": 0.5,
|
||||
"1": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/exact_dynamic.qasm",
|
||||
"qasm": "OPENQASM 3.1;\nqubit[2] q;\nbit c;\nh q[0];\nc = measure q[0];\nif (c) x q[1];\n",
|
||||
"expect": {
|
||||
"exact": "Q502"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
8
wai/quantum-conformance/qasm3/lang/aliases.qasm
Normal file
8
wai/quantum-conformance/qasm3/lang/aliases.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[6] q;
|
||||
qubit r;
|
||||
let evens = q[0:2:5];
|
||||
let tail = q[-2:] ++ r;
|
||||
h evens;
|
||||
x tail;
|
||||
cx q[{1, 3}], q[{2, 4}];
|
||||
11
wai/quantum-conformance/qasm3/lang/aliases.ref.qasm
Normal file
11
wai/quantum-conformance/qasm3/lang/aliases.ref.qasm
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[6] q;
|
||||
qubit r;
|
||||
h q[0];
|
||||
h q[2];
|
||||
h q[4];
|
||||
x q[4];
|
||||
x q[5];
|
||||
x r;
|
||||
cx q[1], q[2];
|
||||
cx q[3], q[4];
|
||||
6
wai/quantum-conformance/qasm3/lang/angle_round.qasm
Normal file
6
wai/quantum-conformance/qasm3/lang/angle_round.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.1;
|
||||
// An angle[4] holds 4 bits of a turn: pi/3 is held as 3/16 of a turn.
|
||||
qubit q;
|
||||
angle[4] t = pi / 3;
|
||||
h q;
|
||||
rz(t) q;
|
||||
4
wai/quantum-conformance/qasm3/lang/angle_round.ref.qasm
Normal file
4
wai/quantum-conformance/qasm3/lang/angle_round.ref.qasm
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
h q;
|
||||
rz(3 * pi / 8) q;
|
||||
7
wai/quantum-conformance/qasm3/lang/bits_known.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/bits_known.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
// A bit register set by a constant is known until a measurement writes it.
|
||||
qubit[2] q;
|
||||
bit[2] b = "10";
|
||||
if (b == 2) x q[0];
|
||||
if (b[0]) x q[1];
|
||||
b = measure q;
|
||||
7
wai/quantum-conformance/qasm3/lang/break_continue.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/break_continue.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[8] q;
|
||||
for int i in [0:7] {
|
||||
if (i == 2) continue;
|
||||
if (i == 5) break;
|
||||
x q[i];
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[8] q;
|
||||
x q[0];
|
||||
x q[1];
|
||||
x q[3];
|
||||
x q[4];
|
||||
11
wai/quantum-conformance/qasm3/lang/calibration.qasm
Normal file
11
wai/quantum-conformance/qasm3/lang/calibration.qasm
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
OPENQASM 3.1;
|
||||
// Calibrations kept verbatim for export, never run.
|
||||
defcalgrammar "openpulse";
|
||||
cal {
|
||||
extern port d0;
|
||||
}
|
||||
defcal x $0 {
|
||||
play(d0, gaussian(1.0, 160dt, 40dt));
|
||||
}
|
||||
qubit q;
|
||||
h q;
|
||||
13
wai/quantum-conformance/qasm3/lang/conditions.qasm
Normal file
13
wai/quantum-conformance/qasm3/lang/conditions.qasm
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
OPENQASM 3.1;
|
||||
// Comparisons, &&, || and ! on measured bits.
|
||||
qubit[3] p;
|
||||
qubit[3] t;
|
||||
bit[3] c;
|
||||
bit[3] r;
|
||||
x p[1];
|
||||
x p[2];
|
||||
c = measure p;
|
||||
if (c >= 6 && !c[0]) x t[0];
|
||||
if (c < 6 || c == 7) x t[1];
|
||||
if (c > 4 && c <= 6) x t[2];
|
||||
r = measure t;
|
||||
7
wai/quantum-conformance/qasm3/lang/ctrl_any.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/ctrl_any.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
// Controls on any gate: a rotation under two controls, and a negative control.
|
||||
qubit[3] q;
|
||||
x q[0];
|
||||
x q[1];
|
||||
ctrl(2) @ ry(pi / 3) q[0], q[1], q[2];
|
||||
negctrl @ x q[2], q[0];
|
||||
7
wai/quantum-conformance/qasm3/lang/ctrl_user.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/ctrl_user.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
gate g a { h a; t a; }
|
||||
h q[0];
|
||||
ctrl @ g q[0], q[1];
|
||||
ctrl @ rz(0.7) q[1], q[0];
|
||||
ctrl @ U(0.1, 0.2, 0.3) q[0], q[1];
|
||||
7
wai/quantum-conformance/qasm3/lang/ctrl_user.ref.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/ctrl_user.ref.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q[0];
|
||||
ch q[0], q[1];
|
||||
cp(pi / 4) q[0], q[1];
|
||||
crz(0.7) q[1], q[0];
|
||||
cu(0.1, 0.2, 0.3, 0) q[0], q[1];
|
||||
10
wai/quantum-conformance/qasm3/lang/def.qasm
Normal file
10
wai/quantum-conformance/qasm3/lang/def.qasm
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
OPENQASM 3.1;
|
||||
include "stdgates.inc";
|
||||
// Subroutines inlined: qubits by reference, classical arguments by value,
|
||||
// values returned.
|
||||
qubit[3] q;
|
||||
def layer(qubit a, qubit b, float[64] t) { h a; cx a, b; rz(t) b; }
|
||||
def half(float[64] x) -> float[64] { return x / 2; }
|
||||
def twice(int[32] k) -> int[32] { return 2 * k; }
|
||||
layer(q[0], q[1], half(pi / 2));
|
||||
layer(q[1], q[2], pi / twice(4));
|
||||
8
wai/quantum-conformance/qasm3/lang/def.ref.qasm
Normal file
8
wai/quantum-conformance/qasm3/lang/def.ref.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[3] q;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
rz(pi / 4) q[1];
|
||||
h q[1];
|
||||
cx q[1], q[2];
|
||||
rz(pi / 8) q[2];
|
||||
21
wai/quantum-conformance/qasm3/lang/def_measure.qasm
Normal file
21
wai/quantum-conformance/qasm3/lang/def_measure.qasm
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
OPENQASM 3.1;
|
||||
// Teleportation as a subroutine with bits of its own, fed forward, and a
|
||||
// subroutine whose returned measurement lands in the caller's bit.
|
||||
qubit[3] q;
|
||||
bit[1] r;
|
||||
def teleport(qubit src, qubit mid, qubit dst) {
|
||||
bit a;
|
||||
bit b;
|
||||
h mid;
|
||||
cx mid, dst;
|
||||
cx src, mid;
|
||||
h src;
|
||||
a = measure src;
|
||||
b = measure mid;
|
||||
if (b) x dst;
|
||||
if (a) z dst;
|
||||
}
|
||||
def read_out(qubit s) -> bit { return measure s; }
|
||||
x q[0];
|
||||
teleport(q[0], q[1], q[2]);
|
||||
r[0] = read_out(q[2]);
|
||||
6
wai/quantum-conformance/qasm3/lang/exact_dynamic.qasm
Normal file
6
wai/quantum-conformance/qasm3/lang/exact_dynamic.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
bit c;
|
||||
h q[0];
|
||||
c = measure q[0];
|
||||
if (c) x q[1];
|
||||
4
wai/quantum-conformance/qasm3/lang/exact_not_dyadic.qasm
Normal file
4
wai/quantum-conformance/qasm3/lang/exact_not_dyadic.qasm
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
h q;
|
||||
rz(pi / 3) q;
|
||||
19
wai/quantum-conformance/qasm3/lang/exported.qasm
Normal file
19
wai/quantum-conformance/qasm3/lang/exported.qasm
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
OPENQASM 3.0;
|
||||
include "stdgates.inc";
|
||||
gate rzx(_gate_p_0) _gate_q_0, _gate_q_1 {
|
||||
h _gate_q_1;
|
||||
cx _gate_q_0, _gate_q_1;
|
||||
rz(_gate_p_0) _gate_q_1;
|
||||
cx _gate_q_0, _gate_q_1;
|
||||
h _gate_q_1;
|
||||
}
|
||||
bit[3] c;
|
||||
qubit[3] q;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
rzx(1.5707963267948966) q[1], q[2];
|
||||
rzx(-1.5707963267948966) q[1], q[2];
|
||||
cx q[1], q[2];
|
||||
c[0] = measure q[0];
|
||||
c[1] = measure q[1];
|
||||
c[2] = measure q[2];
|
||||
7
wai/quantum-conformance/qasm3/lang/generator.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/generator.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
input uint n;
|
||||
qubit[n] q;
|
||||
h q[0];
|
||||
for uint i in [0:n-2] {
|
||||
cx q[i], q[i + 1];
|
||||
}
|
||||
6
wai/quantum-conformance/qasm3/lang/gphase.qasm
Normal file
6
wai/quantum-conformance/qasm3/lang/gphase.qasm
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q;
|
||||
gphase(0.3);
|
||||
ctrl @ gphase(0.7) q[0];
|
||||
negctrl @ gphase(0.2) q[1];
|
||||
7
wai/quantum-conformance/qasm3/lang/gphase.ref.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/gphase.ref.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q;
|
||||
p(0.7) q[0];
|
||||
x q[1];
|
||||
p(0.2) q[1];
|
||||
x q[1];
|
||||
9
wai/quantum-conformance/qasm3/lang/inv.qasm
Normal file
9
wai/quantum-conformance/qasm3/lang/inv.qasm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
gate g(a) x, y { h x; cx x, y; rz(a) y; s x; }
|
||||
h q[0];
|
||||
t q[1];
|
||||
inv @ g(0.3) q[0], q[1];
|
||||
inv @ sx q[1];
|
||||
inv @ U(0.1, 0.2, 0.3) q[0];
|
||||
inv @ iswap q[0], q[1];
|
||||
24
wai/quantum-conformance/qasm3/lang/inv.ref.qasm
Normal file
24
wai/quantum-conformance/qasm3/lang/inv.ref.qasm
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q[0];
|
||||
t q[1];
|
||||
// g's gates inverted, in reverse order
|
||||
sdg q[0];
|
||||
rz(-0.3) q[1];
|
||||
cx q[0], q[1];
|
||||
h q[0];
|
||||
// sx = h s h
|
||||
h q[1];
|
||||
sdg q[1];
|
||||
h q[1];
|
||||
// U(θ, φ, λ) is rz(φ) ry(θ) rz(λ) up to a phase
|
||||
rz(-0.2) q[0];
|
||||
ry(-0.1) q[0];
|
||||
rz(-0.3) q[0];
|
||||
// iswap = s, s, h, cx, cx, h
|
||||
h q[1];
|
||||
cx q[1], q[0];
|
||||
cx q[0], q[1];
|
||||
h q[0];
|
||||
sdg q[1];
|
||||
sdg q[0];
|
||||
7
wai/quantum-conformance/qasm3/lang/output.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/output.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
output bit[2] c;
|
||||
output int[32] n = 3;
|
||||
output float[64] t = pi / 4;
|
||||
x q[1];
|
||||
c = measure q;
|
||||
4
wai/quantum-conformance/qasm3/lang/physical.qasm
Normal file
4
wai/quantum-conformance/qasm3/lang/physical.qasm
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 3.1;
|
||||
h $0;
|
||||
cx $0, $1;
|
||||
rz(0.2) $2;
|
||||
5
wai/quantum-conformance/qasm3/lang/physical.ref.qasm
Normal file
5
wai/quantum-conformance/qasm3/lang/physical.ref.qasm
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[3] q;
|
||||
h q[0];
|
||||
cx q[0], q[1];
|
||||
rz(0.2) q[2];
|
||||
7
wai/quantum-conformance/qasm3/lang/pow.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/pow.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
gate g a, b { h a; cx a, b; t b; }
|
||||
pow(3) @ g q[0], q[1];
|
||||
pow(-2) @ rx(0.4) q[0];
|
||||
pow(4) @ t q[1];
|
||||
pow(0) @ h q[0];
|
||||
7
wai/quantum-conformance/qasm3/lang/pow.ref.qasm
Normal file
7
wai/quantum-conformance/qasm3/lang/pow.ref.qasm
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q[0]; cx q[0], q[1]; t q[1];
|
||||
h q[0]; cx q[0], q[1]; t q[1];
|
||||
h q[0]; cx q[0], q[1]; t q[1];
|
||||
rx(-0.8) q[0];
|
||||
z q[1];
|
||||
9
wai/quantum-conformance/qasm3/lang/qasm2.qasm
Normal file
9
wai/quantum-conformance/qasm3/lang/qasm2.qasm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 2.0;
|
||||
include "qelib1.inc";
|
||||
qreg q[2];
|
||||
creg c[2];
|
||||
u3(pi, 0, pi) q[0];
|
||||
u2(0, pi) q[1];
|
||||
u1(pi/2) q[1];
|
||||
CX q[0], q[1];
|
||||
measure q -> c;
|
||||
8
wai/quantum-conformance/qasm3/lang/qasm2_if.qasm
Normal file
8
wai/quantum-conformance/qasm3/lang/qasm2_if.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 2.0;
|
||||
include "qelib1.inc";
|
||||
qreg q[2];
|
||||
creg c[2];
|
||||
x q[0];
|
||||
measure q -> c;
|
||||
if(c==1) x q[1];
|
||||
measure q[1] -> c[1];
|
||||
2
wai/quantum-conformance/qasm3/lang/refuse_caret.qasm
Normal file
2
wai/quantum-conformance/qasm3/lang/refuse_caret.qasm
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
qubit q;
|
||||
rz(2 ^ 3) q;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
duration d = durationof({ x q; });
|
||||
4
wai/quantum-conformance/qasm3/lang/refuse_extern.qasm
Normal file
4
wai/quantum-conformance/qasm3/lang/refuse_extern.qasm
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 3.1;
|
||||
extern f(int) -> int;
|
||||
qubit q;
|
||||
rz(f(1)) q;
|
||||
4
wai/quantum-conformance/qasm3/lang/refuse_opaque.qasm
Normal file
4
wai/quantum-conformance/qasm3/lang/refuse_opaque.qasm
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
OPENQASM 2.0;
|
||||
qreg q[1];
|
||||
opaque g a;
|
||||
g q[0];
|
||||
3
wai/quantum-conformance/qasm3/lang/refuse_root.qasm
Normal file
3
wai/quantum-conformance/qasm3/lang/refuse_root.qasm
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
pow(0.5) @ U(0.1, 0.2, 0.3) q;
|
||||
5
wai/quantum-conformance/qasm3/lang/refuse_runtime.qasm
Normal file
5
wai/quantum-conformance/qasm3/lang/refuse_runtime.qasm
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
bit c;
|
||||
c = measure q;
|
||||
int k = c;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
rz(1/2) q;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
foo q;
|
||||
10
wai/quantum-conformance/qasm3/lang/root.qasm
Normal file
10
wai/quantum-conformance/qasm3/lang/root.qasm
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q[0];
|
||||
h q[1];
|
||||
pow(0.5) @ x q[0];
|
||||
pow(0.5) @ z q[1];
|
||||
pow(0.5) @ s q[0];
|
||||
pow(0.25) @ rz(1.2) q[1];
|
||||
pow(-0.5) @ x q[1];
|
||||
pow(0.5) @ cz q[0], q[1];
|
||||
10
wai/quantum-conformance/qasm3/lang/root.ref.qasm
Normal file
10
wai/quantum-conformance/qasm3/lang/root.ref.qasm
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[2] q;
|
||||
h q[0];
|
||||
h q[1];
|
||||
sx q[0];
|
||||
s q[1];
|
||||
t q[0];
|
||||
rz(0.3) q[1];
|
||||
sxdg q[1];
|
||||
cp(pi / 2) q[0], q[1];
|
||||
13
wai/quantum-conformance/qasm3/lang/runtime_break.qasm
Normal file
13
wai/quantum-conformance/qasm3/lang/runtime_break.qasm
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
OPENQASM 3.1;
|
||||
// `break` on a measured bit: a jump forward past the rest of the loop.
|
||||
qubit q;
|
||||
qubit[3] t;
|
||||
bit c;
|
||||
bit[3] r;
|
||||
for int i in [0:2] {
|
||||
c = measure q;
|
||||
if (c) break;
|
||||
x t[i];
|
||||
x q;
|
||||
}
|
||||
r = measure t;
|
||||
49
wai/quantum-conformance/qasm3/lang/stdgates.qasm
Normal file
49
wai/quantum-conformance/qasm3/lang/stdgates.qasm
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
OPENQASM 3.1;
|
||||
include "stdgates.inc";
|
||||
// Every standard gate, once, after a layer that leaves no symmetry.
|
||||
qubit[3] q;
|
||||
U(0.31, 0.72, -0.4) q[0];
|
||||
U(1.13, -0.25, 0.9) q[1];
|
||||
U(2.07, 0.5, 0.33) q[2];
|
||||
CX q[0], q[1];
|
||||
CX q[1], q[2];
|
||||
U(0.6, 1.1, -0.7) q[0];
|
||||
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.41) q[1];
|
||||
ry(-1.3) q[2];
|
||||
rz(0.77) q[0];
|
||||
p(1.9) q[1];
|
||||
phase(0.2) q[2];
|
||||
u1(-0.6) q[0];
|
||||
u2(0.3, -1.2) q[1];
|
||||
u3(0.8, 0.1, 2.2) q[2];
|
||||
U(1.4, -0.9, 0.35) q[0];
|
||||
cx q[0], q[1];
|
||||
CX q[2], q[0];
|
||||
cy q[1], q[2];
|
||||
cz q[2], q[0];
|
||||
ch q[0], q[2];
|
||||
cp(0.9) q[1], q[0];
|
||||
cphase(-1.1) q[2], q[1];
|
||||
crx(0.6) q[0], q[1];
|
||||
cry(-0.8) q[1], q[2];
|
||||
crz(1.7) q[2], q[0];
|
||||
cu(0.5, 0.25, -0.75, 0.4) q[0], q[2];
|
||||
swap q[1], q[2];
|
||||
iswap q[0], q[1];
|
||||
rxx(0.45) q[1], q[2];
|
||||
ryy(-0.65) q[0], q[2];
|
||||
rzz(1.25) q[0], q[1];
|
||||
ccx q[0], q[1], q[2];
|
||||
ccz q[2], q[0], q[1];
|
||||
cswap q[1], q[2], q[0];
|
||||
77
wai/quantum-conformance/qasm3/lang/stdgates.ref.qasm
Normal file
77
wai/quantum-conformance/qasm3/lang/stdgates.ref.qasm
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
OPENQASM 3.1;
|
||||
// The same gates, each written in U and CX alone.
|
||||
gate d_x a { U(pi, 0, pi) a; }
|
||||
gate d_y a { U(pi, pi / 2, pi / 2) a; }
|
||||
gate d_z a { U(0, 0, pi) a; }
|
||||
gate d_h a { U(pi / 2, 0, pi) a; }
|
||||
gate d_s a { U(0, 0, pi / 2) a; }
|
||||
gate d_sdg a { U(0, 0, -pi / 2) a; }
|
||||
gate d_t a { U(0, 0, pi / 4) a; }
|
||||
gate d_tdg a { U(0, 0, -pi / 4) a; }
|
||||
gate d_p(l) a { U(0, 0, l) a; }
|
||||
gate d_rx(t) a { U(t, -pi / 2, pi / 2) a; }
|
||||
gate d_ry(t) a { U(t, 0, 0) a; }
|
||||
gate d_rz(t) a { U(0, 0, t) a; }
|
||||
gate d_sx a { d_h a; d_s a; d_h a; }
|
||||
gate d_sxdg a { d_h a; d_sdg a; d_h a; }
|
||||
gate d_cz a, b { d_h b; CX a, b; d_h b; }
|
||||
gate d_cy a, b { d_sdg b; CX a, b; d_s b; }
|
||||
gate d_ch a, b { d_h b; d_sdg b; CX a, b; d_h b; d_t b; CX a, b; d_t b; d_h b; d_s b; d_x b; d_s a; }
|
||||
gate d_cp(l) a, b { d_p(l / 2) a; CX a, b; d_p(-l / 2) b; CX a, b; d_p(l / 2) b; }
|
||||
gate d_crz(l) a, b { d_rz(l / 2) b; CX a, b; d_rz(-l / 2) b; CX a, b; }
|
||||
gate d_crx(l) a, b { d_p(pi / 2) b; CX a, b; U(-l / 2, 0, 0) b; CX a, b; U(l / 2, -pi / 2, 0) b; }
|
||||
gate d_cry(l) a, b { d_ry(l / 2) b; CX a, b; d_ry(-l / 2) b; CX a, b; }
|
||||
gate d_cu(t, f, l, g) a, b { d_p(g) a; d_p((l + f) / 2) a; d_p((l - f) / 2) b; CX a, b; U(-t / 2, 0, -(f + l) / 2) b; CX a, b; U(t / 2, f, 0) b; }
|
||||
gate d_swap a, b { CX a, b; CX b, a; CX a, b; }
|
||||
gate d_iswap a, b { d_s a; d_s b; d_h a; CX a, b; CX b, a; d_h b; }
|
||||
gate d_rzz(t) a, b { CX a, b; d_rz(t) b; CX a, b; }
|
||||
gate d_rxx(t) a, b { d_h a; d_h b; d_rzz(t) a, b; d_h a; d_h b; }
|
||||
gate d_ryy(t) a, b { d_rx(pi / 2) a; d_rx(pi / 2) b; d_rzz(t) a, b; d_rx(-pi / 2) a; d_rx(-pi / 2) b; }
|
||||
gate d_ccx a, b, c { d_h c; CX b, c; d_tdg c; CX a, c; d_t c; CX b, c; d_tdg c; CX a, c; d_t b; d_t c; d_h c; CX a, b; d_t a; d_tdg b; CX a, b; }
|
||||
gate d_ccz a, b, c { d_h c; d_ccx a, b, c; d_h c; }
|
||||
gate d_cswap a, b, c { CX c, b; d_ccx a, b, c; CX c, b; }
|
||||
qubit[3] q;
|
||||
U(0.31, 0.72, -0.4) q[0];
|
||||
U(1.13, -0.25, 0.9) q[1];
|
||||
U(2.07, 0.5, 0.33) q[2];
|
||||
CX q[0], q[1];
|
||||
CX q[1], q[2];
|
||||
U(0.6, 1.1, -0.7) q[0];
|
||||
d_x q[0];
|
||||
d_y q[1];
|
||||
d_z q[2];
|
||||
d_h q[0];
|
||||
d_s q[1];
|
||||
d_sdg q[2];
|
||||
d_t q[0];
|
||||
d_tdg q[1];
|
||||
d_sx q[2];
|
||||
d_sxdg q[0];
|
||||
d_rx(0.41) q[1];
|
||||
d_ry(-1.3) q[2];
|
||||
d_rz(0.77) q[0];
|
||||
d_p(1.9) q[1];
|
||||
d_p(0.2) q[2];
|
||||
d_p(-0.6) q[0];
|
||||
U(pi / 2, 0.3, -1.2) q[1];
|
||||
U(0.8, 0.1, 2.2) q[2];
|
||||
U(1.4, -0.9, 0.35) q[0];
|
||||
CX q[0], q[1];
|
||||
CX q[2], q[0];
|
||||
d_cy q[1], q[2];
|
||||
d_cz q[2], q[0];
|
||||
d_ch q[0], q[2];
|
||||
d_cp(0.9) q[1], q[0];
|
||||
d_cp(-1.1) q[2], q[1];
|
||||
d_crx(0.6) q[0], q[1];
|
||||
d_cry(-0.8) q[1], q[2];
|
||||
d_crz(1.7) q[2], q[0];
|
||||
d_cu(0.5, 0.25, -0.75, 0.4) q[0], q[2];
|
||||
d_swap q[1], q[2];
|
||||
d_iswap q[0], q[1];
|
||||
d_rxx(0.45) q[1], q[2];
|
||||
d_ryy(-0.65) q[0], q[2];
|
||||
d_rzz(1.25) q[0], q[1];
|
||||
d_ccx q[0], q[1], q[2];
|
||||
d_ccz q[2], q[0], q[1];
|
||||
d_cswap q[1], q[2], q[0];
|
||||
18
wai/quantum-conformance/qasm3/lang/switch.qasm
Normal file
18
wai/quantum-conformance/qasm3/lang/switch.qasm
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[3] q;
|
||||
bit[3] c;
|
||||
const int mode = 2;
|
||||
switch (mode) {
|
||||
case 1 { x q[0]; }
|
||||
case 2, 3 { x q[1]; }
|
||||
default { h q[0]; }
|
||||
}
|
||||
c[0] = measure q[1];
|
||||
c[1] = measure q[0];
|
||||
switch (c[0:1]) {
|
||||
case 0 { }
|
||||
case 1 { x q[2]; }
|
||||
case 2 { h q[2]; }
|
||||
default { }
|
||||
}
|
||||
c[2] = measure q[2];
|
||||
13
wai/quantum-conformance/qasm3/lang/timing.qasm
Normal file
13
wai/quantum-conformance/qasm3/lang/timing.qasm
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
OPENQASM 3.1;
|
||||
// Durations carried, and labelled as not applied by the method.
|
||||
qubit[2] q;
|
||||
stretch s;
|
||||
duration d = 100ns;
|
||||
h q[0];
|
||||
delay[2 * d] q[0];
|
||||
box [1us] {
|
||||
cx q[0], q[1];
|
||||
}
|
||||
delay[s] q[1];
|
||||
barrier q;
|
||||
x[20ns] q[1];
|
||||
18
wai/quantum-conformance/qasm3/lang/types.qasm
Normal file
18
wai/quantum-conformance/qasm3/lang/types.qasm
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
OPENQASM 3.1;
|
||||
// Classical types, arithmetic, casts and built-in functions, folded on reading.
|
||||
qubit q;
|
||||
const float[64] half = 0.5;
|
||||
angle[3] quarter = pi / 2;
|
||||
complex[float[64]] z = 1.0 + 2.0im;
|
||||
uint[8] u = 250;
|
||||
u += 3;
|
||||
int[8] k = int[8](-3.7);
|
||||
const bit[4] mask = "1010";
|
||||
array[int[32], 3] a = {1, 2, 3};
|
||||
rx(half * pi) q;
|
||||
rz(quarter) q;
|
||||
ry(real(z * z)) q;
|
||||
rz(float(u) / 1000) q;
|
||||
rx(k) q;
|
||||
ry(popcount(mask) + a[2]) q;
|
||||
rz(sqrt(4.0) + arctan(1.0) * 4 - pi) q;
|
||||
9
wai/quantum-conformance/qasm3/lang/types.ref.qasm
Normal file
9
wai/quantum-conformance/qasm3/lang/types.ref.qasm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
rx(pi / 2) q;
|
||||
rz(pi / 2) q;
|
||||
ry(-3.0) q;
|
||||
rz(0.253) q;
|
||||
rx(-3.0) q;
|
||||
ry(5.0) q;
|
||||
rz(2.0) q;
|
||||
10
wai/quantum-conformance/qasm3/lang/while_rus.qasm
Normal file
10
wai/quantum-conformance/qasm3/lang/while_rus.qasm
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
OPENQASM 3.1;
|
||||
// Repeat until success on measured bits, under a declared bound.
|
||||
qubit q;
|
||||
bit c;
|
||||
c = measure q;
|
||||
@wai.max_iterations 3
|
||||
while (c == 0) {
|
||||
x q;
|
||||
c = measure q;
|
||||
}
|
||||
13
wai/quantum-conformance/qasm3/lang/while_static.qasm
Normal file
13
wai/quantum-conformance/qasm3/lang/while_static.qasm
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[4] q;
|
||||
int i = 0;
|
||||
while (i < 4) {
|
||||
h q[i];
|
||||
i += 1;
|
||||
}
|
||||
int j = 3;
|
||||
while (true) {
|
||||
if (j < 1) break;
|
||||
x q[j];
|
||||
j -= 2;
|
||||
}
|
||||
8
wai/quantum-conformance/qasm3/lang/while_static.ref.qasm
Normal file
8
wai/quantum-conformance/qasm3/lang/while_static.ref.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.1;
|
||||
qubit[4] q;
|
||||
h q[0];
|
||||
h q[1];
|
||||
h q[2];
|
||||
h q[3];
|
||||
x q[3];
|
||||
x q[1];
|
||||
8
wai/quantum-conformance/qasm3/lang/while_unbounded.qasm
Normal file
8
wai/quantum-conformance/qasm3/lang/while_unbounded.qasm
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
OPENQASM 3.1;
|
||||
qubit q;
|
||||
bit c;
|
||||
c = measure q;
|
||||
while (c == 0) {
|
||||
x q;
|
||||
c = measure q;
|
||||
}
|
||||
690
wai/quantum-conformance/qasm3/manifest.json
Normal file
690
wai/quantum-conformance/qasm3/manifest.json
Normal file
|
|
@ -0,0 +1,690 @@
|
|||
{
|
||||
"format": "wai.qasm3-conformance/1",
|
||||
"about": "OpenQASM 3 programs, each with what the reader must do with it. spec/ holds the language specification's example programs, unchanged; lang/ holds a program for each construct, and references written without it.",
|
||||
"expectations": {
|
||||
"refused": "reading refuses the program with this diagnostic code",
|
||||
"warns": "reading succeeds, and these are the codes of every warning and note it gives, sorted",
|
||||
"deterministic": "every shot of a run gives this outcome (bit n-1 first)",
|
||||
"distribution": "the exact probabilities of the outcomes of a program whose measurements all come at the end, within 1e-9",
|
||||
"expectations": "Pauli expectation values of the state before the final measurements, exact, within 1e-9",
|
||||
"equivalent": "the program's unitary equals the named reference's, up to a global phase, within 1e-9",
|
||||
"exact": "the bit-exact circuit takes the program (ok), or refuses it with this code",
|
||||
"outputs": "the run's result lists these outputs",
|
||||
"timing": "the run's result labels its durations as not applied",
|
||||
"calibrations": "the program keeps this many calibration statements verbatim",
|
||||
"inputs": "the generator's inputs"
|
||||
},
|
||||
"cases": [
|
||||
{
|
||||
"file": "spec/adder.qasm",
|
||||
"covers": [
|
||||
"gate definitions",
|
||||
"uint indexed as bits",
|
||||
"casts",
|
||||
"for over a range with a negative step",
|
||||
"slices in measurement"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "10000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/alignment.qasm",
|
||||
"covers": [
|
||||
"stretch",
|
||||
"delay with a stretch expression",
|
||||
"barrier"
|
||||
],
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q403"
|
||||
],
|
||||
"timing": true,
|
||||
"distribution": {
|
||||
"000": 0.8535533905932737,
|
||||
"100": 0.14644660940672624
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/arrays.qasm",
|
||||
"covers": [
|
||||
"arrays",
|
||||
"nested array values",
|
||||
"slices",
|
||||
"sizeof",
|
||||
"an index past the array's end (the example's own: `a - 1` is 4)"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q107"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/cphase.qasm",
|
||||
"covers": [
|
||||
"a fragment: no qubits declared"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q102"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/dd.qasm",
|
||||
"covers": [
|
||||
"durationof"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/defcal.qasm",
|
||||
"covers": [
|
||||
"defcal",
|
||||
"defcalgrammar"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q100"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/gateteleport.qasm",
|
||||
"covers": [
|
||||
"extern",
|
||||
"subroutine bits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/inverseqft1.qasm",
|
||||
"covers": [
|
||||
"conditions on a cast of measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "0000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/inverseqft2.qasm",
|
||||
"covers": [
|
||||
"conditions on single bits",
|
||||
"measure ->"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "0000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/ipe.qasm",
|
||||
"covers": [
|
||||
"angle arithmetic on measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q128"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/msd.qasm",
|
||||
"covers": [
|
||||
"subroutines",
|
||||
"an index outside its register"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q107"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/qec.qasm",
|
||||
"covers": [
|
||||
"a subroutine returning measured bits",
|
||||
"conditions on a cast"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "01000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/qft.qasm",
|
||||
"covers": [
|
||||
"cphase",
|
||||
"reset before the first gate"
|
||||
],
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"0000": 0.0625,
|
||||
"0001": 0.0625,
|
||||
"0010": 0.0625,
|
||||
"0011": 0.0625,
|
||||
"0100": 0.0625,
|
||||
"0101": 0.0625,
|
||||
"0110": 0.0625,
|
||||
"0111": 0.0625,
|
||||
"1000": 0.0625,
|
||||
"1001": 0.0625,
|
||||
"1010": 0.0625,
|
||||
"1011": 0.0625,
|
||||
"1100": 0.0625,
|
||||
"1101": 0.0625,
|
||||
"1110": 0.0625,
|
||||
"1111": 0.0625
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/qpt.qasm",
|
||||
"covers": [
|
||||
"empty gate bodies",
|
||||
"barrier"
|
||||
],
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"0": 0.5,
|
||||
"1": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/rb.qasm",
|
||||
"covers": [
|
||||
"a Clifford sequence"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/rus.qasm",
|
||||
"covers": [
|
||||
"while on measured bits with no bound",
|
||||
"bits set by a constant"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q310"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/scqec.qasm",
|
||||
"covers": [
|
||||
"subroutines called as gates",
|
||||
"bits known on reading",
|
||||
"extern"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/t1.qasm",
|
||||
"covers": [
|
||||
"durations",
|
||||
"durationof"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/teleport.qasm",
|
||||
"covers": [
|
||||
"teleportation",
|
||||
"conditions",
|
||||
"an empty gate"
|
||||
],
|
||||
"expect": {
|
||||
"expectations": {
|
||||
"Z2": 0.955336489125606
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/varteleport.qasm",
|
||||
"covers": [
|
||||
"let rebinding a name of an enclosing scope"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q101"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "spec/vqe.qasm",
|
||||
"covers": [
|
||||
"extern"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/def.qasm",
|
||||
"covers": [
|
||||
"def",
|
||||
"return"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/def.ref.qasm",
|
||||
"exact": "ok"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/def_measure.qasm",
|
||||
"covers": [
|
||||
"def with bits of its own",
|
||||
"a returned measurement"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/inv.qasm",
|
||||
"covers": [
|
||||
"inv @ on standard and user gates"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/inv.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/pow.qasm",
|
||||
"covers": [
|
||||
"pow(k) @, k a whole number"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/pow.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/root.qasm",
|
||||
"covers": [
|
||||
"pow(r) @, r fractional, exact roots"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/root.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/ctrl_any.qasm",
|
||||
"covers": [
|
||||
"ctrl @ on a rotation",
|
||||
"negctrl @"
|
||||
],
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"010": 0.75,
|
||||
"111": 0.25
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/ctrl_user.qasm",
|
||||
"covers": [
|
||||
"ctrl @ on a user gate, rz and U"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/ctrl_user.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/types.qasm",
|
||||
"covers": [
|
||||
"float",
|
||||
"angle",
|
||||
"complex",
|
||||
"uint",
|
||||
"bit arrays",
|
||||
"arrays",
|
||||
"casts",
|
||||
"built-in functions"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/types.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/angle_round.qasm",
|
||||
"covers": [
|
||||
"angle[n] rounding"
|
||||
],
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q121"
|
||||
],
|
||||
"equivalent": "lang/angle_round.ref.qasm",
|
||||
"exact": "ok"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/while_static.qasm",
|
||||
"covers": [
|
||||
"while known on reading",
|
||||
"break"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/while_static.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/while_rus.qasm",
|
||||
"covers": [
|
||||
"while on measured bits under a declared bound"
|
||||
],
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q311"
|
||||
],
|
||||
"deterministic": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/while_unbounded.qasm",
|
||||
"covers": [
|
||||
"while on measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q310"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/switch.qasm",
|
||||
"covers": [
|
||||
"switch known on reading",
|
||||
"switch on measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "101"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/break_continue.qasm",
|
||||
"covers": [
|
||||
"break",
|
||||
"continue"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/break_continue.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/runtime_break.qasm",
|
||||
"covers": [
|
||||
"break on a measured bit"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "0011"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/conditions.qasm",
|
||||
"covers": [
|
||||
"comparisons, &&, || and ! on measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "101110"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/output.qasm",
|
||||
"covers": [
|
||||
"output"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "10",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "c",
|
||||
"type": "bit[2]",
|
||||
"bits": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "n",
|
||||
"type": "int[32]",
|
||||
"value": 3
|
||||
},
|
||||
{
|
||||
"name": "t",
|
||||
"type": "float[64]",
|
||||
"value": 0.7853981633974483
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/timing.qasm",
|
||||
"covers": [
|
||||
"delay",
|
||||
"box",
|
||||
"stretch",
|
||||
"barrier",
|
||||
"gate durations"
|
||||
],
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q403"
|
||||
],
|
||||
"timing": true,
|
||||
"distribution": {
|
||||
"01": 0.5,
|
||||
"10": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/calibration.qasm",
|
||||
"covers": [
|
||||
"defcal",
|
||||
"cal",
|
||||
"defcalgrammar"
|
||||
],
|
||||
"expect": {
|
||||
"warns": [
|
||||
"Q450",
|
||||
"Q451",
|
||||
"Q452"
|
||||
],
|
||||
"calibrations": 3,
|
||||
"distribution": {
|
||||
"0": 0.5,
|
||||
"1": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/stdgates.qasm",
|
||||
"covers": [
|
||||
"every standard gate, U and CX"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/stdgates.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/aliases.qasm",
|
||||
"covers": [
|
||||
"let",
|
||||
"slices",
|
||||
"index sets",
|
||||
"negative indices",
|
||||
"++"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/aliases.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/physical.qasm",
|
||||
"covers": [
|
||||
"physical qubits"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/physical.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/gphase.qasm",
|
||||
"covers": [
|
||||
"gphase",
|
||||
"ctrl @ gphase"
|
||||
],
|
||||
"expect": {
|
||||
"equivalent": "lang/gphase.ref.qasm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/bits_known.qasm",
|
||||
"covers": [
|
||||
"bits set by a constant"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "01"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/generator.qasm",
|
||||
"covers": [
|
||||
"input"
|
||||
],
|
||||
"expect": {
|
||||
"inputs": {
|
||||
"n": 4
|
||||
},
|
||||
"distribution": {
|
||||
"0000": 0.5,
|
||||
"1111": 0.5
|
||||
},
|
||||
"exact": "ok"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/qasm2.qasm",
|
||||
"covers": [
|
||||
"OpenQASM 2: qreg, creg, u1, u2, u3, CX, measure ->"
|
||||
],
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"01": 0.5,
|
||||
"11": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/qasm2_if.qasm",
|
||||
"covers": [
|
||||
"OpenQASM 2: if(c==n)"
|
||||
],
|
||||
"expect": {
|
||||
"deterministic": "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/exported.qasm",
|
||||
"covers": [
|
||||
"a program as converters write one: gates with generated names, decimal angles"
|
||||
],
|
||||
"expect": {
|
||||
"distribution": {
|
||||
"000": 0.5,
|
||||
"111": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_root.qasm",
|
||||
"covers": [
|
||||
"a fractional power with no exact gate"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q205"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_extern.qasm",
|
||||
"covers": [
|
||||
"extern"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q125"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_runtime.qasm",
|
||||
"covers": [
|
||||
"classical arithmetic on measured bits"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q306"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_durationof.qasm",
|
||||
"covers": [
|
||||
"durationof"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q405"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_opaque.qasm",
|
||||
"covers": [
|
||||
"opaque"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q126"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_truncating.qasm",
|
||||
"covers": [
|
||||
"a truncating division as a real"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q118"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_caret.qasm",
|
||||
"covers": [
|
||||
"^ between integers with no version"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q119"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/refuse_unknown_gate.qasm",
|
||||
"covers": [
|
||||
"an unknown gate"
|
||||
],
|
||||
"expect": {
|
||||
"refused": "Q103"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/exact_not_dyadic.qasm",
|
||||
"covers": [
|
||||
"the bit-exact method: an angle that is not dyadic"
|
||||
],
|
||||
"expect": {
|
||||
"exact": "Q500",
|
||||
"distribution": {
|
||||
"0": 0.5,
|
||||
"1": 0.5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "lang/exact_dynamic.qasm",
|
||||
"covers": [
|
||||
"the bit-exact method: a dynamic program"
|
||||
],
|
||||
"expect": {
|
||||
"exact": "Q502"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
44
wai/quantum-conformance/qasm3/spec/adder.qasm
Normal file
44
wai/quantum-conformance/qasm3/spec/adder.qasm
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* quantum ripple-carry adder
|
||||
* Cuccaro et al, quant-ph/0410184
|
||||
*/
|
||||
include "stdgates.inc";
|
||||
|
||||
gate majority a, b, c {
|
||||
cx c, b;
|
||||
cx c, a;
|
||||
ccx a, b, c;
|
||||
}
|
||||
|
||||
gate unmaj a, b, c {
|
||||
ccx a, b, c;
|
||||
cx c, a;
|
||||
cx a, b;
|
||||
}
|
||||
|
||||
qubit[1] cin;
|
||||
qubit[4] a;
|
||||
qubit[4] b;
|
||||
qubit[1] cout;
|
||||
bit[5] ans;
|
||||
uint[4] a_in = 1; // a = 0001
|
||||
uint[4] b_in = 15; // b = 1111
|
||||
// initialize qubits
|
||||
reset cin;
|
||||
reset a;
|
||||
reset b;
|
||||
reset cout;
|
||||
|
||||
// set input states
|
||||
for uint i in [0: 3] {
|
||||
if(bool(a_in[i])) x a[i];
|
||||
if(bool(b_in[i])) x b[i];
|
||||
}
|
||||
// add a to b, storing result in b
|
||||
majority cin[0], b[0], a[0];
|
||||
for uint i in [0: 2] { majority a[i], b[i + 1], a[i + 1]; }
|
||||
cx a[3], cout[0];
|
||||
for uint i in [2: -1: 0] { unmaj a[i],b[i+1],a[i+1]; }
|
||||
unmaj cin[0], b[0], a[0];
|
||||
measure b[0:3] -> ans[0:3];
|
||||
measure cout[0] -> ans[4];
|
||||
16
wai/quantum-conformance/qasm3/spec/alignment.qasm
Normal file
16
wai/quantum-conformance/qasm3/spec/alignment.qasm
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* CPMG XY4 decoupling
|
||||
* This example demonstrates the use of stretch to
|
||||
* specify design intent on gate alignment, without
|
||||
* being tied to physical qubits and gates.
|
||||
*/
|
||||
include "stdgates.inc";
|
||||
|
||||
stretch g;
|
||||
|
||||
qubit[3] q;
|
||||
barrier q;
|
||||
cx q[0], q[1];
|
||||
delay[g] q[2];
|
||||
U(pi/4, 0, pi/2) q[2];
|
||||
delay[2*g] q[2];
|
||||
barrier q;
|
||||
101
wai/quantum-conformance/qasm3/spec/arrays.qasm
Normal file
101
wai/quantum-conformance/qasm3/spec/arrays.qasm
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
OPENQASM 3.0; // Version statement is optional
|
||||
|
||||
// ==================
|
||||
// Array declarations
|
||||
// ==================
|
||||
|
||||
// Declare 'my_ints' to be a 1D array of 8-bit signed integers, where the index
|
||||
// runs from 0 to 15.
|
||||
array[int[8], 16] my_ints;
|
||||
|
||||
// Declare 'my_doubles' to be a 2D array of double-precision floating-point
|
||||
// values, where the first index runs from 0 to 7 and the second from 0 to 3.
|
||||
array[float[64], 8, 4] my_doubles;
|
||||
|
||||
// Initialise a 1D array with fixed values.
|
||||
array[uint[32], 4] my_defined_uints = {5, 6, 7, 8};
|
||||
|
||||
// Initialise a 2D array with fixed values.
|
||||
array[float[32], 4, 2] my_defined_floats = {
|
||||
{0.5, 0.5},
|
||||
{1.0, 2.0},
|
||||
{-0.4, 0.7},
|
||||
{1.3, -2.1e-2}
|
||||
};
|
||||
|
||||
// Initialise an array using a row of another array. Note that this copies the
|
||||
// data; changes to the values in `my_defined_float_row` will not affect
|
||||
// `my_defined_floats`.
|
||||
array[float[32], 2] my_defined_float_row = my_defined_floats[0];
|
||||
|
||||
// Arrays can be defined in terms of compile-time constant dimension sizes, and
|
||||
// can use expressions in the slots of their initialisers.
|
||||
const uint[8] DIM_SIZE = 2;
|
||||
array[int[8], DIM_SIZE, DIM_SIZE] all_ones = {{2+3, 4-1}, {3+8, 12-4}};
|
||||
|
||||
|
||||
// =============================
|
||||
// Array indexing and operations
|
||||
// =============================
|
||||
|
||||
// Use `[]` notation to access array elements. The dimensions are
|
||||
// comma-separated.
|
||||
uint[8] a = my_defined_uints[0];
|
||||
float[32] b = my_defined_floats[2, 1];
|
||||
|
||||
// The same notation is used in simple assignments.
|
||||
my_defined_uints[1] = 5;
|
||||
my_defined_floats[3, 0] = -0.45;
|
||||
|
||||
// In both, the indices can be (non-constant) expressions.
|
||||
my_defined_uints[a - 1] = a + 1;
|
||||
|
||||
// Assignments can also be done using an array, or array slice, on the left-hand
|
||||
// side, provided the right-hand side evaluates to an array of exactly the same
|
||||
// shape. The assignment is done by copy, so subsequent changes to either of
|
||||
// the two parts will not affect the other.
|
||||
my_defined_floats[2] = my_defined_float_row;
|
||||
|
||||
// You can also use the slice notation to set elements. Beware that it is
|
||||
// generally a logical error to read and write from overlapping slices at the
|
||||
// same time, and that OpenQASM 3 makes no guarantees about which order the data
|
||||
// will be read from and written to. You might clobber data if you overlap.
|
||||
my_defined_floats[0:1] = my_defined_floats[2:3];
|
||||
|
||||
// The ``sizeof`` operator returns the size of an array's dimension.
|
||||
const uint[32] dimension = sizeof(my_defined_uints); // assigns 4.
|
||||
|
||||
// The ``sizeof`` operator can also be used in two-argument form, where the
|
||||
// second argument is the index of the dimension, counting from 0.
|
||||
const uint[32] first_dimension = sizeof(my_doubles, 0); // returns 8
|
||||
const uint[32] second_dimension = sizeof(my_doubles, 1); // returns 4
|
||||
|
||||
// If the second argument is omitted from ``sizeof`` and the given array is
|
||||
// multi-dimensional, it defaults to returning the first dimension, so
|
||||
// ``sizeof(my_array) == sizeof(my_array, 0)`` in all circumstances.
|
||||
const uint[32] first_dimension = sizeof(my_doubles); // still 8.
|
||||
|
||||
|
||||
// =====================
|
||||
// Arrays in subroutines
|
||||
// =====================
|
||||
|
||||
// Array arguments have a mandatory ``readonly`` or ``mutable`` specifier when
|
||||
// defined in a subroutine argument list. This is because arrays are passed to
|
||||
// subroutines by reference, not by value, so modifications will propagate back
|
||||
// to the original data. Such modifications are only allowed for ``mutable``
|
||||
// references, not ``readonly``.
|
||||
def copy_3_bytes(readonly array[uint[8], 3] in_array, mutable array[uint[8], 3] out_array) {
|
||||
// Within this block, ``in_array`` can be read from, but not written to,
|
||||
// whereas ``out_array`` can be both read from and written to.
|
||||
}
|
||||
|
||||
// When specifying array subroutine parameters, there is a second format where
|
||||
// the sizes of the dimensions are not given explicitly, only the number of
|
||||
// dimensions. This is where the ``sizeof`` operator is most useful. In these
|
||||
// cases, `sizeof` is _not_ a compile-time constant.
|
||||
def multi_dimensional_input(readonly array[int[32], #dim=3] my_array) {
|
||||
uint[32] dimension_0 = sizeof(my_array, 0);
|
||||
uint[32] dimension_1 = sizeof(my_array, 1);
|
||||
uint[32] dimension_2 = sizeof(my_array, 2);
|
||||
}
|
||||
9
wai/quantum-conformance/qasm3/spec/cphase.qasm
Normal file
9
wai/quantum-conformance/qasm3/spec/cphase.qasm
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
gate cphase(θ) a, b
|
||||
{
|
||||
U(0, 0, θ / 2) a;
|
||||
CX a, b;
|
||||
U(0, 0, -θ / 2) b;
|
||||
CX a, b;
|
||||
U(0, 0, θ / 2) b;
|
||||
}
|
||||
cphase(π / 2) q[0], q[1];
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue