diff --git a/.github/wai-conformance/verifiers/quantum-receipts.sh b/.github/wai-conformance/verifiers/quantum-receipts.sh index 5c85c7fa9..18c06083a 100644 --- a/.github/wai-conformance/verifiers/quantum-receipts.sh +++ b/.github/wai-conformance/verifiers/quantum-receipts.sh @@ -16,6 +16,6 @@ python3 -I wai/quantum-conformance/receipts/generate.py --check python3 -I wai/quantum-conformance/receipts/generate.py --self-test python3 -I wai/quantum-conformance/tools/receipt_verify.py --self-test wai/wai-quantum/src/engine/testdata/es-number-tostring.txt -for plant in lenient-key no-alg last-duplicate no-inexact measured-simulator whole-cap lax-small-order-r no-canonical-spelling set-seal-only names-layout-only; do +for plant in lenient-key no-alg last-duplicate no-inexact measured-simulator whole-cap lax-small-order-r no-canonical-spelling set-seal-only names-layout-only route-unchecked choice-unchecked distance-unchecked; do python3 -I wai/quantum-conformance/tools/receipt_differential.py --second-only --plant "$plant" | tail -1 done diff --git a/.github/workflows/wai-quantum-cli.yml b/.github/workflows/wai-quantum-cli.yml index 83dbfb69f..ec12fa75e 100644 --- a/.github/workflows/wai-quantum-cli.yml +++ b/.github/workflows/wai-quantum-cli.yml @@ -101,8 +101,11 @@ jobs: working-directory: wai/wai-quantum-cli run: | set -euo pipefail - cargo test --locked --release 2>&1 | tee "$RUNNER_TEMP/test.log" + # No test reaches a person's timings: every test here names its file, + # so none may appear where a person's would be. + XDG_CONFIG_HOME="$RUNNER_TEMP/no-timings" 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; } + test ! -e "$RUNNER_TEMP/no-timings/wai/quantum-timings.json" || { echo "::error::a test wrote the timings of whoever runs it"; exit 1; } # Your own providers end to end (tests/providers.rs), against the # reference provider this binary serves, and their jobs as MCP # tasks, each test by name. @@ -119,7 +122,27 @@ jobs: an_agent_lists_estimates_is_refused_and_runs_only_with_confirm_cost \ an_agent_runs_on_a_provider_as_a_task_and_the_server_answers_while_it_waits \ providers::tasks::tests::a_job_reads_as_its_task \ - providers::tasks::tests::a_cancelled_request_ends_its_wait_and_a_change_wakes_it; do + providers::tasks::tests::a_cancelled_request_ends_its_wait_and_a_change_wakes_it \ + a_contract_weighs_every_route_and_its_receipt_says_why \ + an_agent_weighs_a_contract_and_runs_on_the_route_it_chooses \ + a_run_is_stopped_at_its_ceiling_by_a_live_reading_and_its_receipt_says_so \ + a_route_nothing_can_stop_is_refused_under_a_ceiling_on_every_surface \ + an_estimate_refuses_a_job_clearly_past_a_ceiling_and_keeps_to_its_build \ + estimates::tests::the_timings_keep_each_method_s_last_runs_and_read_back \ + estimates::tests::three_runs_read_give_an_estimate_and_none_of_them_a_promise \ + estimates::tests::a_route_nothing_can_read_or_stop_has_no_watch \ + estimates::tests::a_run_in_its_own_process_is_killed_at_its_ceiling_and_read_whole \ + estimates::tests::readings_are_kept_under_the_machine_reader_and_build \ + estimates::tests::a_counter_is_asked_twice_and_a_reading_kept_nowhere_is_not_taken \ + a_run_under_a_ceiling_ends_with_its_command_line \ + keys::tests::keys_made_at_once_are_one_key \ + estimates::tests::a_run_is_read_only_where_something_needs_the_reading \ + estimates::tests::the_wait_for_a_counter_is_in_no_run_s_power \ + estimates::tests::a_package_counter_is_read_over_a_few_of_its_updates \ + estimates::tests::the_timings_are_kept_where_their_variables_say \ + estimates::tests::runs_that_finish_together_all_keep_theirs \ + estimates::tests::a_file_that_is_no_store_is_kept_and_a_link_stays_a_link \ + tests::the_command_line_parses_as_documented; do grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/test.log" || { echo "::error::$t did not run and pass"; exit 1; } done # The model harness and the views in an agent's host, each test by name. @@ -183,7 +206,8 @@ jobs: # of a duplicate member kept, inexact numbers let through, a simulator's counts let pass as # measured, a ceiling on every whole number, R of small order let through, the canonical # spelling of a large double refused, a set's seal checked and nothing of its items, - # qubit names held to the layouts only) must make the + # qubit names held to the layouts only, and under a contract each route's outcome, the + # planner's choice or a shadow's distance taken as it stands) must make the # differential fail: the proof that it can. A plant that the corpus alone catches is caught # by the second-only run too, in the independent verifiers' step. - name: Job receipts, two verifiers @@ -194,9 +218,12 @@ jobs: python3 -I wai/quantum-conformance/receipts/generate.py --self-test python3 -I wai/quantum-conformance/tools/receipt_verify.py --self-test wai/wai-quantum/src/engine/testdata/es-number-tostring.txt python3 -I wai/quantum-conformance/tools/receipt_differential.py --reference wai/wai-quantum-cli/target/release/wai-quantum - for plant in lenient-key no-alg last-duplicate no-inexact measured-simulator whole-cap lax-small-order-r no-canonical-spelling set-seal-only names-layout-only; do - python3 -I wai/quantum-conformance/tools/receipt_differential.py --reference wai/wai-quantum-cli/target/release/wai-quantum --plant "$plant" | tail -1 - done + # Each plant runs the whole differential with one verifier broken on purpose, a few + # minutes each: they run side by side, and every one must be caught. + printf '%s\n' lenient-key no-alg last-duplicate no-inexact measured-simulator whole-cap lax-small-order-r no-canonical-spelling set-seal-only names-layout-only route-unchecked choice-unchecked distance-unchecked \ + | xargs -P "$(nproc)" -I{} bash -c 'set -o pipefail; python3 -I wai/quantum-conformance/tools/receipt_differential.py --reference wai/wai-quantum-cli/target/release/wai-quantum --plant "{}" | tail -1' \ + | tee "$RUNNER_TEMP/plants.log" + test "$(grep -c ': caught' "$RUNNER_TEMP/plants.log")" -eq 13 || { echo "::error::not every plant was caught"; exit 1; } # The release binary, pinned by version and SHA-256, rather than a build from source. # Every WAI workflow that runs wasmtime pins this one version, and every run passes # -W nan-canonicalization=y -W relaxed-simd-deterministic=y: every NaN a float @@ -243,6 +270,13 @@ 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 nan-canonicalization=y -W relaxed-simd-deterministic=y "$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; } + # With a home it can reach, a run still gives its result, and keeps nothing: + # a wasm build reads no counter and writes no timings. + mkdir -p "$RUNNER_TEMP/wasi-home" + for e in HOME=/h WAI_QUANTUM_TIMINGS=/h/timings.json; do + wasmtime run -W nan-canonicalization=y -W relaxed-simd-deterministic=y --env "$e" --dir "$RUNNER_TEMP/wasi-home::/h" "$w" run --demo-key --json --shots 100 < "$RUNNER_TEMP/p.qasm" 2> /dev/null | python3 -c 'import json,sys; assert sum(json.load(sys.stdin)["result"]["counts"].values())==100' + done + test -z "$(find "$RUNNER_TEMP/wasi-home" -type f)" || { echo "::error::a wasm build kept a file"; 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" @@ -282,7 +316,8 @@ jobs: working-directory: wai/wai-quantum-cli run: | set -euo pipefail - nice -n 10 cargo test --locked --release --features metal 2>&1 | tee "$RUNNER_TEMP/test.log" + XDG_CONFIG_HOME="$RUNNER_TEMP/no-timings" nice -n 10 cargo test --locked --release --features metal 2>&1 | tee "$RUNNER_TEMP/test.log" + test ! -e "$RUNNER_TEMP/no-timings/wai/quantum-timings.json" || { echo "::error::a test wrote the timings of whoever runs it"; exit 1; } grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/test.log" || { echo "::error::no test ran"; exit 1; } nice -n 10 cargo clippy --locked --release --all-targets --features metal -- -D warnings - name: The smoke checks, and a run on the GPU diff --git a/.github/workflows/wai-quantum-qpu.yml b/.github/workflows/wai-quantum-qpu.yml index a676dfc92..738f142b9 100644 --- a/.github/workflows/wai-quantum-qpu.yml +++ b/.github/workflows/wai-quantum-qpu.yml @@ -79,10 +79,11 @@ jobs: # 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" - # The library (81, the cloud-tasks client's 26 among them), the clients - # against their contracts (15), and the providers end to end (12), each - # binary's count pinned. - for n in 81 15 12; do + # The library (93 here, the cloud-tasks client's and a job under a contract's + # among them; the macOS keychain's test makes 94 on macOS, run by the leg + # below), the clients against their contracts (17), and the providers end + # to end (12), each binary's count pinned. + for n in 93 17 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 \ @@ -109,7 +110,18 @@ jobs: cloud_tasks::tests::a_task_is_asked_after_in_the_region_its_id_names \ registry::tests::a_kind_this_build_does_not_know_is_kept_and_the_rest_is_read \ a_cloud_task_cancelled_while_it_waits_ends_cancelled \ - cloud_tasks_round_trip_through_their_contract a_job_collected_later_is_read_through_the_qubits_it_was_sent_on; do + cloud_tasks_round_trip_through_their_contract a_job_collected_later_is_read_through_the_qubits_it_was_sent_on \ + job::tests::a_contract_is_weighed_before_anything_is_sent job::tests::a_cost_ceiling_holds_the_estimate_and_is_no_confirmation \ + job::tests::every_provider_is_weighed_against_the_engine_s_own_methods job::tests::a_shadow_and_its_reasoning_outlive_what_sent_the_job \ + job::tests::a_deadline_it_cannot_be_held_to_is_refused_and_one_that_leaves_no_time_says_so \ + job::tests::a_job_past_its_deadline_is_cancelled_where_it_waits \ + job::tests::a_provider_the_contract_does_not_allow_is_asked_nothing \ + job::tests::the_word_for_a_routed_run_binds_the_provider_and_says_only_itself \ + job::tests::a_job_past_its_deadline_ends_only_on_the_provider_s_word \ + job::tests::a_reasoning_no_receipt_could_give_is_not_taken_up \ + job::tests::a_word_confirms_one_run_and_binds_its_contract \ + job::tests::an_open_provider_says_it_cannot_cancel_and_that_its_estimate_is_the_least \ + a_built_in_kind_runs_under_a_contract_and_a_classical_method_shadows_it a_cost_estimated_at_the_least_it_can_come_to_meets_no_ceiling; do grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/test.log" || { echo "::error::$t did not run and pass"; exit 1; } done - name: Clippy diff --git a/.github/workflows/wai-quantum-registry.yml b/.github/workflows/wai-quantum-registry.yml index c4cfd673f..a0384d10e 100644 --- a/.github/workflows/wai-quantum-registry.yml +++ b/.github/workflows/wai-quantum-registry.yml @@ -97,15 +97,35 @@ jobs: grep -q "^test engine::registry::tests::$t \.\.\. ok$" "$RUNNER_TEMP/$log.log" || { echo "::error::$t did not run ($log)"; exit 1; } done done - - name: The built-ins' bytes, the refusal table and the job layer beside them + - name: The built-ins' bytes, the refusal table, the job layer and the planner under a contract beside them shell: bash working-directory: wai/wai-quantum run: | set -euo pipefail - cargo test --locked --release --features full --lib -- engine::job:: engine::refusal:: engine::catalog:: engine::compile:: engine::formats:: 2>&1 | tee "$RUNNER_TEMP/engine.log" + cargo test --locked --release --features full --lib -- engine::job:: engine::refusal:: engine::catalog:: engine::compile:: engine::formats:: engine::planner:: 2>&1 | tee "$RUNNER_TEMP/engine.log" grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$RUNNER_TEMP/engine.log" || { echo "::error::the engine's tests did not pass"; exit 1; } for t in engine::job::tests::a_job_that_asks_for_no_verdict_gives_the_bytes_it_gave \ - engine::refusal::tests::the_documented_table_is_the_table; do + engine::refusal::tests::the_documented_table_is_the_table \ + engine::planner::tests::what_the_routes_cost_is_the_same_bytes_on_every_host \ + engine::planner::tests::nothing_falls_back_from_exact_to_approximate \ + engine::planner::tests::nothing_falls_back_between_a_simulator_and_a_device \ + engine::planner::tests::every_rule_a_verifier_holds_a_local_contract_job_to_is_broken_once_and_found_alone \ + engine::planner::tests::every_rule_a_verifier_holds_a_provider_s_contract_job_to_is_broken_once_and_found_alone \ + engine::planner::tests::an_energy_ceiling_is_held_by_a_live_reading_and_a_stopped_run_says_so \ + engine::planner::tests::a_shadow_is_a_method_s_run_of_exactly_the_job_s_program \ + engine::planner::tests::a_shadow_the_host_says_failed_is_run_again \ + engine::planner::tests::under_a_contract_a_provider_is_used_only_where_it_allows_one \ + engine::planner::tests::what_a_price_may_state_is_bounded_and_past_it_is_an_unknown \ + engine::planner::tests::a_local_route_is_free_and_kept_states_exactly_the_charge \ + engine::planner::tests::auto_is_what_the_routes_give_and_cannot_be_lowered \ + engine::planner::tests::a_device_target_s_job_names_its_method_beside_the_host_s_providers \ + engine::planner::tests::a_named_approximate_simulator_runs_under_a_contract_that_names_no_class \ + engine::planner::tests::the_sampling_bound_holds_for_sparse_and_dense_outcomes \ + engine::planner::tests::a_named_provider_s_routes_carry_the_class_their_shadow_has \ + engine::planner::tests::a_built_in_route_and_a_result_are_held_to_their_method_s_classes \ + engine::planner::tests::what_a_receipt_states_of_itself_is_of_its_form \ + engine::planner::tests::recheck_plans_the_shadow_again_and_leaves_the_host_s_routes_to_the_host \ + engine::planner::tests::a_target_s_and_a_pulse_program_s_deadline_is_reported_kept; do grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run"; exit 1; } done # A gate held whole through a job, and the meter that holds a matrix diff --git a/.github/workflows/wai-quantum-service.yml b/.github/workflows/wai-quantum-service.yml index 1b2cefde9..7120e150c 100644 --- a/.github/workflows/wai-quantum-service.yml +++ b/.github/workflows/wai-quantum-service.yml @@ -80,6 +80,15 @@ jobs: 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 the_service_gives_every_receipt_the_verdict_the_corpus_gives_it \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the service was not held to the corpus of receipts"; exit 1; } + grep -q '^test jobs::tests::a_route_s_figure_is_an_estimate_and_what_reads_the_run \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the service's routes did not say what reads them"; exit 1; } + grep -q '^test energy::tests::a_mac_whose_counter_reads_nothing_has_no_meter \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::a Mac that reads nothing was given a meter"; exit 1; } + grep -q '^test a_job_is_stopped_at_its_energy_ceiling_and_its_receipt_says_so \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the service did not stop a job at its ceiling"; exit 1; } + # A job under a contract: met or refused with every route's reason, never routed to a + # provider, stopped at its deadline, and its reasoning kept across a restart. + for t in a_contract_is_met_or_refused_and_the_service_never_reaches_a_provider \ + jobs::tests::a_contract_job_keeps_its_reasoning_across_a_restart; 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 # The engine's parts of the service, each required by name: sets and # sweeps and their Merkle paths, a result's provenance, the package @@ -100,6 +109,11 @@ jobs: engine::energy::tests::the_probe_finds_a_live_counter_s_cadence_and_refuses_a_stalled_one \ engine::energy::tests::only_top_level_package_zones_are_read_and_a_frozen_one_is_not_live \ engine::energy::tests::a_package_figure_names_its_scope_and_declares_its_edges \ + engine::energy::tests::a_host_s_estimate_rests_on_its_own_runs_and_says_whose \ + engine::energy::tests::a_live_reading_stops_at_the_ceiling_and_a_silent_second_loses_it \ + engine::energy::tests::an_exited_read_far_below_its_cpu_time_is_no_reading \ + engine::energy::tests::a_package_counter_added_up_read_by_read_keeps_every_range \ + engine::energy::tests::a_counter_s_reading_is_trusted_only_within_one_wrap \ qasm::tests::a_bound_parameter_reads_as_the_program_written_with_its_value; do grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run"; exit 1; } done @@ -117,6 +131,19 @@ jobs: trap 'kill $pid 2>/dev/null || true; cat "$RUNNER_TEMP/service.log"' EXIT for _ in $(seq 1 50); do curl -s -o /dev/null http://127.0.0.1:18241/v1/health && break; sleep 0.2; done bash smoke.sh http://127.0.0.1:18241 + # The image as it ships: built, run with the service as the container's first + # process (pid 1, no --init, as deploy/Containerfile and docs/self-host.md run + # it), and held to the same smoke checks, which run jobs through its workers. + # A runner with no container engine says so; one with an engine must pass. + - name: The image as it ships + shell: bash + run: | + set -euo pipefail + if command -v podman >/dev/null 2>&1; then engine=podman + elif command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then engine=docker + else echo "::warning::this runner has no container engine, so the shipped image was not run"; exit 0; fi + ENGINE=$engine JOBS=8 bash wai/wai-quantum-service/deploy/check-image.sh + grep -q '^test the_service_runs_its_jobs_as_pid_1 \.\.\. ok$' "$RUNNER_TEMP/test.log" || { echo "::error::the service was not run as pid 1"; exit 1; } service-macos: name: service · macos diff --git a/wai/REGISTRY.md b/wai/REGISTRY.md index 2838baa85..d1a04339a 100644 --- a/wai/REGISTRY.md +++ b/wai/REGISTRY.md @@ -455,12 +455,15 @@ and a role are fixed once registered. | `wai.quantum.docs-manifest/1` | a document with no schema file: the list of documents tools/quantum-docs checks | | `wai.quantum.write/1` | a document with no schema file: the transcript wai-quantum-writer keeps of writing a program for a task | | `wai.quantum.model/1` | a document with no schema file: the manifest of a writer's model, the file wai-model.json (wai-quantum-writer's `coder`) | +| `wai.quantum.timings/1` | a document with no schema file: the runs the command line has timed and read the energy of on this machine, by method, that its estimate of a job's energy rests on (wai-quantum-cli's `estimates`) | | `wai.quantum.job-key/1` | a digest domain: the digest a job service keeps a client's idempotency key under, the client's name beside the key (wai-quantum-service) | | `wai.quantum.trace/1` | a digest domain: an optimisation trace's first link is BLAKE3 of it and the request's canonical text (wai-quantum's `engine::variational`) | | `wai.quantum.circuit3` | refused on purpose: not a capability; the circuit core's test gives it to see no gateset read from it | | `wai.quantum.other` | refused on purpose: not a kernel; the fabric's test puts it in a certificate to see the placement refuse that certificate | | `wai.quantum.x/one` | refused on purpose: not a schema's name, its major not a number; the schema module's test gives it to see no file named for it | | `wai.quantum.job-result/2` | refused on purpose: a major of the job result's schema that no text defines; a test writes it into a sealed result to see the receipt fail | +| `wai.quantum.planner/2` | refused on purpose: a format of a contract job's reasoning that no text defines; the planner's test and the job receipts corpus seal it in a result to see the reasoning refused (quantum-providers §8.7) | +| `wai.quantum.timings/9` | refused on purpose: a major of the command line's timings that no text defines; its test writes it to see the file kept aside and a new one begun | | `wai.quantum.target/2` | refused on purpose: a major of the device target's schema that no text defines; the targets' test gives it to see the document refused | | `wai.quantum.provider/2` | refused on purpose: a version of the provider protocol that no text defines; the reference provider's test sends it to see it answered unsupported_version (quantum-providers §10) | | `wai.quantum.provider/9` | refused on purpose: a version of the provider protocol that no text defines; the protocol schema's test sends it to see it answered unsupported_version (quantum-providers §10) | diff --git a/wai/changes/2026-11-06-wai-quantum-cli-energy-estimate.md b/wai/changes/2026-11-06-wai-quantum-cli-energy-estimate.md new file mode 100644 index 000000000..42a9c61b1 --- /dev/null +++ b/wai/changes/2026-11-06-wai-quantum-cli-energy-estimate.md @@ -0,0 +1,45 @@ +### wai-quantum: an energy ceiling is held by a live reading, and the command line can give one + +- **A `max_joules` is held while the job runs.** No figure before a run can promise what it will take: the work a plan + states leaves out what drives its time. So the run is a process of its own, on the command line as in the service, + read about every ten milliseconds as the host schedules it and killed at the ceiling, so the work stops there + (`engine::energy::Watcher`). Its whole figure is read when it ends, killed or not, and sealed: a stopped receipt says + what the run took in all and the longest time between two reads, and a run that passed its ceiling between two reads + and finished is sealed as having missed it. A run so stopped gives no answer, + its result has `stopped` and the accuracy class `none`, its `kept.energy` says the ceiling was not kept, it is sealed + like any result, and a command line exits 4 (section 8.7, the new reason `stopped`, in both verifiers). A counter that + stops reading for a second of time leaves nothing holding the ceiling, so the run is stopped and nothing is sealed; a + run that fails ends the watch at once. +- **Where nothing can read and stop a run, the route is refused** under a ceiling, with why (`energy_unwatched`, the new + route code): a host with no counter, a method on a device no counter reads, a provider, and a run in a process with + other work in it, as an MCP or LSP server's is. A route states what would read it (`energy.watch`) or why nothing + would (`energy.unwatched`). +- **The figure before a run stays, as an estimate.** `price.energy.joules` is the median of the method's last three or + more runs read on this host, labelled an estimate with what it covers. It can refuse a job clearly past a ceiling + (`energy`), and it promises nothing; with no history a run under a ceiling goes ahead, since the reading holds it. + The service's dry runs' `time` and `energy` are the same bytes as before. +- **`--max-joules` works on the command line.** Around a `run` the command line reads the energy counter the engine + reads (this process's own CPU energy on macOS, the processor packages' on Linux where they may be read), when a + ceiling asks or the method has fewer than three runs read: never otherwise, so that a run on Linux does not pay for + finding out that a counter is live, which is found once in a process. It keeps the run's work, its times and its power + in `$WAI_QUANTUM_TIMINGS` (`off` keeps none), `$XDG_CONFIG_HOME/wai/quantum-timings.json` or + `~/.config/wai/quantum-timings.json`, the last 32 runs of each method on each machine, reader, build version, profile + and feature set, under a lock, written whole through any link. A file that is no store of timings is kept aside with + a note, never written over. Only `run` reads and keeps: a server, a test or an embedded runner reads nothing, since + its other threads would be in the reading, and a wasm build keeps no file and reads no counter. +- **What is read is read fairly.** The wait for a process's counter is in the energy and not in the time the power is + taken over. A package counter is read over at least four of its updates, the step it can be short by added, and a + reading past the time a counter can wrap twice is no reading. +- **The fourth check.** A run's process ends with the one that watches it (its standard input stays open, and on + Linux the kernel kills it with its parent), so a command line killed mid-run leaves nothing computing. A package's + counter is added up read by read for the whole figure, so a run past the counter's range is read in full; a whole + figure below what stopped a run is no reading, and both verifiers hold a stopped receipt's figure and time. A counter + that stands still while the run spends CPU time is frozen, and loses the run as silence does; the longest gap counts + the time before the first read. On macOS a worker leaves the core before it exits, and an exited read far below its + CPU time is no reading. SIGCHLD is set to its default before a run is waited for, and a reading kept nowhere is not + taken. +- **Two processes making a key at once.** A new key was created empty and then written, so a process starting in that + moment read an empty file and died, or found the file there and died; a test that discards standard error saw only + silence. A key now appears whole or not at all, and the one that finds a key there reads it. +- **Nothing is sealed that is not a reading.** A run that finished, read in its own process, is never a complete reading, + so a result here still says its energy is unmetered, and a contract's `kept.energy` says it is not known. diff --git a/wai/changes/2026-11-06-wai-quantum-planner-under-a-contract.md b/wai/changes/2026-11-06-wai-quantum-planner-under-a-contract.md new file mode 100644 index 000000000..3cc6f1658 --- /dev/null +++ b/wai/changes/2026-11-06-wai-quantum-planner-under-a-contract.md @@ -0,0 +1,83 @@ +### wai-quantum: the planner under a contract, its reasoning sealed, and a provider's answer shadowed + +- **A contract in the job request** (`contract`, [quantum-providers.md §8.7](extensions/quantum-providers.md)): the + class wanted (`exactness`), a cost ceiling (`max_cost`, an amount in decimals and its currency), a deadline + (`deadline_seconds`), an energy ceiling (`max_joules`) and whether a provider may be used (`providers`: `never`, the + default, or `allowed`). Under a contract a provider is used, asked for an estimate or named only where it allows one: + a provider named under one that does not is refused (`J070`). The ceiling bounds the estimate a route is chosen by, + not what is charged after. A job without a contract plans as it did, byte for byte. A contract that does not read is refused + (`J070`), member by member, rather than read as absent; a set refuses one (`J073`). +- **The planner** (`engine::planner`) lists every route the host can see: each method here, and each of the person's + providers a host brings. It prices each with what is known: a method's memory and work as the planner counts them, its + time at the planner's nominal rate where its work predicts it, its energy where the host estimates one; a provider's + own estimate, with what it leaves out (`time`, `amount`, `energy`, `mitigation`, `decoder`, `charged`, `cancel`). It rejects + every route that cannot meet the contract, each with a code and a sentence, and runs the cheapest of the rest. An + unknown never passes: a time nobody states does not meet a deadline, nor an unknown cost a ceiling, nor an estimate + that is only the least a job can come to (`cost_at_least`), nor an energy nobody estimates. Nothing falls back, from + exact to approximate or between a simulator and a device. With no route left, the job is refused with every route's + reason (`J071`). A contract that names no class keeps `auto`'s pick while it meets the rest, and only a route at least + as exact may take its place. A price states at most 10^12 seconds and an amount of at most 64 characters; past + either, the host states it unknown. Routes are ordered by money (free first, then amounts by value), then time to the + nearest millisecond, then a method here before a provider, then memory and name: a total order, the same in both + verifiers. +- **The reasoning is sealed** in the result as `planner` (`wai.quantum.planner/1`): every route, its price or why it was + rejected, what the job names, the question it asks and each method's rank in `auto`'s order, so that `auto` is + recomputed rather than taken on the host's word, the choice, what is the same on every host (`stable`: a digest of + what the host-independent routes cost, pinned by a test on x86_64 and arm64, cut-rank's anneal now on the engine's + own exp and ln so that its plan is the same bits everywhere), and what the contract kept against what happened + (`kept`: the deadline, the energy, and the charge, which is the result's). Both verifiers recompute each route's + outcome and the choice from what the receipt states, and give nine new reasons (`contract_form`, + `contract_provider`, `planner_form`, `planner_route`, `planner_choice`, `planner_stable`, `planner_kept`, + `contract_class`, `shadow`); the differential holds them to the same choice, class, kept and shadow distance, not + only the same reasons. The corpus gains eleven made receipts under a contract and eighty-one crafted ones, + each of the review's single-rule changes to the second verifier is found by them, and three plants prove the + differential sees a route, a choice and a distance taken as they stand. +- **A provider's answer is shadowed.** When a provider answers a contract job, the most exact classical method that can + reach the same counts within the time the contract leaves runs too, on a seed of its own, and the result carries both + with their distance (total variation exactly, as whole numbers; Hellinger fidelity; and `sampling_tvd_bound`, a + bound on what the shots alone would leave that holds for sparse outcomes as for dense ones). A shadow is a method's + run of exactly the job's program, shots and a seed of its own, with no other member; its counts are whole and sum to + its shots. Where none can run, the result says which tried and why. `wai-quantum verify --recheck` prices the routes + again, checks `auto`, and runs the shadow again, a shadow the host says failed among them. +- **What a receipt states of itself is held to the job.** A built-in method's route, and a local result, have a class of + that method's, as section 8.7's table gives; a shadow's class too. A route to a method is host-dependent or not by + what it is, `host.providers` names exactly the provider routes, and a method a provider-named job shadows is listed + with the class it has on this job. `wai-quantum verify --recheck` plans the shadow again on the same engine, compares + what the job named, and leaves the routes a host brought to that host, in text as in a parsed value. +- **Nothing is sent that could not be sealed.** A provider's route is held to section 8.7 before it is sent (`before_sending`), + so a paid job whose receipt would be refused costs nothing, and a provider the contract does not allow is asked + nothing, in `plan`, `start` and `run` alike. Under a contract a provider is asked only where the contract names a + class one could give (`measured`, `simulated` or `any`). The word that confirms a routed run binds the provider, the + device and its identity beside the route, the estimate and the program, and says only itself. A job past its deadline + ends only on the provider's word that it was cancelled: one whose client cannot cancel says so (`cancel` in + `leaves_out`), and stays waiting. A target's and a pulse program's deadline is held to a host's timer. +- **What ran is the route chosen.** A provider's result names its route's device and provenance, and its cost is the + route's money, or the choice does not hold (`planner_choice`): a run sealed at 50 USD on a route called free, or a + paid run sealed as free, is found. A provider's route has the class its provenance gives; every built-in method's + route but stabilizer's, stabilizer-rank's and cut-rank's has the one class its table gives (a matrix product state's + is `heuristic`); a method the host registered is host-dependent; a shadow's outcomes are as long as the provider's. + A recheck of a receipt sealed by another engine whose shadow did not run says what this engine plans and does not + say it holds. A routed run's word binds the contract too and sends one run. An open-protocol provider may say in + `describe` that it cannot cancel (`cancels`), and in an estimate that its amount is the least the job can come to + (`at_least`), and its price says so. +- **The fourth check.** Both verifiers compare a route and its result alike: numbers by value, a boolean only to a + boolean, `null` as absent. Under a contract a provider's result of the earlier form is refused (`contract_form`). A + recheck across engine versions gives `holds` `null`, and reads the job's memory by value. A word's count and its + run's record are taken under one lock, and a run the provider took spends the word whatever became of it. A job + that names a provider under a class no provider's counts have is refused (`J071`) before the provider is asked. + CI runs the verifier plants side by side. +- **Every host seals only what its verifier accepts.** A result short of the class its reasoning wants gives no answer + (`J072`), and each host checks a contract job's reasoning before it seals it. A run past its contract's deadline on the + job service is stopped, and the command line cancels a provider's job still waiting at it (`J074`). A deadline holds + a method's own run time, and a provider's from submission to its counts. +- **Surfaces.** `wai-quantum run` and `plan` take `--exactness`, `--max-cost`, `--deadline`, `--max-joules`, + `--allow-providers` and `--contract`; `--deadline` and `--max-joules` take a finite number above 0; a run that kept + less than it asked exits 4. A run the planner routes to a provider that is not free is confirmed by `--confirm WORD` + (`confirm` for an agent), the word its dry run gives for that route, its estimate and its program, and is refused + if any has changed; `--yes` confirms only a provider the person names. The local MCP server gains + `plan_routes` and `run_routed`, which weigh the person's providers beside the methods here; the engine's run and plan + tools take a contract and reach no provider. The free job service takes a contract, lists no provider among its + routes, holds `max_joules` by a live reading of its worker, and keeps a queued job's reasoning across a restart. +- **Found on the way.** A pulse job refused any `contract` member (`J040`): it now takes one. A route's class for a + method that declares several is the first class each of them meets, so `single` and `bounded` together are + `heuristic`. diff --git a/wai/extensions/quantum-providers.md b/wai/extensions/quantum-providers.md index d6ac9e52b..fbe365f2a 100644 --- a/wai/extensions/quantum-providers.md +++ b/wai/extensions/quantum-providers.md @@ -180,6 +180,7 @@ No fields. The answer describes the device: | `max_shots` | optional: the most shots a job may ask | | `seeded` | optional: `true` when a job's `seed` makes its counts reproducible (a simulator) | | `approximate` | optional, with `simulator` or `emulator`: `true` when its results are approximate (a truncated tensor network, a sampled Pauli path); a result is then labelled so (§8.1) | +| `cancels` | optional: `false` when it cannot cancel a job it took (§5.6), so that a client can say so before it sends one | A client MUST NOT take a device to be free unless `billing` says `"free": true`, or an estimate says so (§5.2). @@ -200,6 +201,7 @@ Fields: `program` (§4), `shots`. The answer, before anything is submitted: | `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 | +| `at_least` | optional: `true` when the amount is only the least the job can come to, as with a device billed by the time a job turns out to take | | `note` | optional | A provider that cannot estimate answers `unsupported`; the client then treats @@ -299,8 +301,9 @@ object holding `request`, the job as it was asked, and `result`, which carries its `receipt`. This section says what a provider's result carries (§8.1), how it is sealed and read (§8.2), what its counts' source and its `execution` say (§8.3), what a verifier checks and the reason it gives for each failure -(§8.4), and what the receipt proves (§8.5). A verifier of §8.2 and §8.4 checks -any job's receipt, a provider's or not. +(§8.4), what the receipt proves (§8.5), and what a job under a contract carries +beside it (§8.7). A verifier of §8.2, §8.4 and §8.7 checks any job's receipt, a +provider's or not. ### 8.1 What a provider's result carries @@ -548,7 +551,7 @@ as a set: none for a valid receipt. It is valid exactly when there is none. | `bad_signature` | the signature does not hold, strictly (§8.2), over the digest the receipt states (so a body changed after it was sealed gives `digest_mismatch` alone) | | `inexact_number` | a whole number written as one, in what the receipt seals (the request, and the result less its receipt; for a set, the request and its head, §8.6) and sealed as a double (§8.2), is not a double, and is not the canonical text of the double it reads as. A receipt is of the first form when `receipt_form` is not reported and it has no `canon`; one that `receipt_form` refuses names no form, and its numbers are read as a canonical receipt's | | `provider_class` | a provider's result whose `accuracy.class` is not the one its form gives: `measured` in the earlier form; in the stated form, `measured` for `silicon` and `simulated` for a provenance whose part before any `:` is `simulator` or `emulator` (none for any other); or whose `accuracy.approximate` is present and not `true`, or `true` in the earlier form or on a class other than `simulated`. Or a result of another method whose class is `measured` or `simulated` | -| `request_provider` | a provider's result whose `provider.name` is not a string equal to the request's `provider` | +| `request_provider` | a provider's result whose `provider.name` is not a string equal to the request's `provider`; or, when the request gives none (or `null`) and its `contract.providers` is `allowed`, equal to what follows `provider:` in `planner.choice` (§8.7) | | `request_shots` | a provider's result whose `shots` is not the request's (1024 when the request gives none, or `null`) | | `counts` | a provider's result whose `counts` is not an object of outcomes, all of one length and each of `0` and `1` only, to whole numbers from 1 to 2^53 − 1; or whose `shots` (a whole number of at least 1), `omitted_shots` and `distinct_outcomes` (whole numbers of at least 0) are missing; or whose counts and `omitted_shots` do not sum to `shots`; or whose `distinct_outcomes` is not the number of outcomes listed when `omitted_shots` is 0; or, when it is not 0, lists other than 65,536 outcomes, or no more distinct outcomes than it lists | | `provider_members` | a stated provider's result (below) without, or with a wrong type of: `provider`'s `name`, `kind`, `protocol` and `device` (each a string not empty), `provenance` (as `provider_class` reads it), `describe` (64 lower-case hex digits), `qubits` (a whole number of at least 1) and `basis` (equal to `compiled.basis`); `calibration` (a string or `null`); `compiled`'s `basis` (`rzsxxcz`, `prxcz` or `gpizz`), `program` (64 lower-case hex digits), `qasm3` (a string), `native_gates`, `two_qubit_gates` and `swaps` (whole numbers of at least 0), `layout` and `final_layout` (arrays of whole numbers of at least 0) and `checked` (a string); `compiled.qubit_names`, where it is given or required, is below; `job`'s `id` (a string not empty) and `polls` (a whole number of at least 0); `ideal.computed` (`true` or `false`); `cost`'s `free` and `confirmed` (each `true` or `false`), `estimate` (an object) and `charged` (`null`, or an object whose `amount` and `currency` are strings); `energy.unmetered` (a string), and `energy.service_kwh_is` (a string) when there is `energy.service_kwh`; `schema` (`wai.quantum.job-result/1`); `engine.name` (`wai-quantum`) and `engine.version` (a string) | @@ -556,6 +559,7 @@ as a set: none for a valid receipt. It is valid exactly when there is none. | `execution` | a stated provider's result whose `execution` breaks a rule of §8.3; or, for a kind with rows, is neither one of the rows that hold for its provenance nor stated by `nobody`; or, for `http` and `process`, is not stated by `provider` or `nobody` | | `compiled_program` | a stated provider's result whose `compiled.program` is not the BLAKE3 of `compiled.qasm3`'s UTF-8 bytes, when `qasm3` is a string and `program` is 64 lower-case hex digits | | `cost_confirmation` | a stated provider's result whose `cost.confirmed` is `true` on a free run or `false` on one that is not free (§7), when both are `true` or `false` | +| `contract_form`, `planner_form`, `planner_route`, `planner_choice`, `planner_stable`, `planner_kept`, `contract_class`, `shadow`, `stopped` | §8.7, for any job's result, a provider's or not | A provider's result is one whose `method` is `provider`. It is *stated* when it carries a member `counts_source` or a member `execution` (whatever their @@ -600,7 +604,8 @@ counts' source and its `execution`, each as the result gives it. These are all the rules: what §8.1 names and this table does not check (`compiled.hash` and `placement`, the notes, the `ideal` figures, the -estimate's contents) is the host's word, unchecked. The schemas +estimate's contents, a route's price where §8.7 does not recompute from it) is +the host's word, unchecked. The schemas (`wai.quantum.job-result/1`, `wai.quantum.receipt/2`) describe what a host writes; a verifier judges by this section. @@ -686,6 +691,420 @@ whether each `qasm` is that program (`derived`, beside the reasons); that is the engine's check of the set, not a rule of its receipt, and a verifier that does not write programs out does not make it. +### 8.7 A job under a contract + +A job says what it wants of an answer in its request's `contract`, and the +planner that took it says why the route it chose was the one, in its result's +`planner`. A *contract job* is one whose request holds a `contract` member other +than `null`. A job with none carries neither `planner` nor `shadow`, and plans as +it did before this section was written, byte for byte. + +**The contract.** An object of these members, each optional; `null` is absent. + +| member | | +|---|---| +| `exactness` | the class wanted: a string of the table below | +| `max_cost` | the most a provider's estimate of the run may come to, before it runs: an object of exactly `amount`, an amount in decimals (one or more digits, optionally `.` and one or more digits, at most 64 characters in all), and `currency`, a string not empty. It bounds the estimate, not the charge, which no one knows before the run: what was charged is stated after it, beside the ceiling (`kept.cost`) | +| `deadline_seconds` | a number above 0: when it must be done by, in seconds, as below | +| `max_joules` | a number above 0: the most energy the run may take, in joules, enforced while it runs: a live reading stops it when it reaches this, and the receipt says so (below). A route with no live reading is refused under a ceiling. Nothing before a run can promise a figure: a job's work leaves out what drives its time, and the same job read twice differs | +| `providers` | `never` or `allowed`: whether a route may be one of the person's providers. `never` is the default, given or not, and a request that names a `provider` under a contract that does not allow one is refused (`J070`) | + +A contract of any other form is refused (`J070`). So is any other member, which +read as absent would be a requirement dropped in silence. + +`exactness` is met by these classes of a result (§8.1, and the engine's own): + +| wanted | met by | +|---|---| +| `bit-exact` | `bit-exact` | +| `exact` | `bit-exact`, `exact` | +| `single` | `bit-exact`, `exact`, `single` | +| `bounded` | `bit-exact`, `exact`, `bounded` | +| `estimate` | `bit-exact`, `exact`, `bounded`, `estimate` | +| `heuristic` | `bit-exact`, `exact`, `single`, `bounded`, `estimate`, `heuristic` | +| `measured` | `measured` | +| `simulated` | `simulated`, on a result that is not `approximate` | +| `any` | every class | + +This is a table and not a ladder: `single` states no bound, so it does not meet +`bounded`, and a device's counts are in no classical class. + +**What a deadline measures.** For a run of one of the engine's methods, the time +the engine took over the run itself (the result's `elapsed_ms`): not the queue, the +planning, a restart before it, the check of its intents, nor the sealing. For a +provider's run, the time from the job's submission to the moment the host first +finds it finished: the provider's queue and its run count, and a host that comes +back to a job late (one sent without waiting, collected later) counts the wait +too, so its `elapsed_ms` can only overstate. A shadow is not counted: it runs in +what the deadline leaves, or not at all. A host that can stop a run stops it at +its deadline: the job service stops its worker, and nothing is sealed (`J074`). A +provider's job is looked at only while a host follows it: past the deadline, the +next look cancels it where the client can, and it is `cancelled` once the provider +says so (`J074`). A job no one follows, or one a client cannot cancel (its route +says so: `cancel` in `leaves_out`), runs on and can be billed; when it finishes, +`kept.deadline` says it was missed. + +**What a ceiling measures, and how it is held.** `max_joules` is held by a live +reading, while the run goes: a host runs the job in a process of its own, reads the +route's `watch` every few milliseconds as the host's scheduler allows, and kills that +process when the reading reaches the ceiling, so the work stops there; only a host +that can stop a run can give a route a `watch`. The reading is of what `watch` says, and of nothing +else: a process's own CPU energy leaves out memory, the host's idle draw and any +device it drives, so a method on a GPU or an accelerator has no `watch`; a processor +package's counts every process on it, so a busy host stops a run sooner. A run can +pass the ceiling by what it takes between two reads, and by what a counter has not +yet shown. A host that runs a job inside a process doing other work, or that reads +nothing, gives no `watch`, nor does a provider's route: the route is refused under a +ceiling (`energy_unwatched`). A counter that stops reading during a run leaves nothing +holding the ceiling: the host stops the run after a second of time without a reading, +or with one that stood still while the run spent CPU time (a frozen counter is not a +live one), and seals nothing. The run's process ends with the process that watches +it, however that one ends. A host reads the run's process whole when it ends, killed or not (a package's +counter added up read by read, each step corrected for a wrap, so that a run passing +the counter's range is read in full; a process's read that is far below what its CPU +time implies is no reading), and seals that figure in `energy`, so a run that passed its ceiling between two reads +and finished is sealed as having missed it. + +A run so stopped gave no answer. Its result has no member but `method`, `qubits`, +`gates`, `accuracy`, `stopped`, `elapsed_ms`, `planner`, `energy`, `engine`, `schema` +and `receipt`, so no counts, expectations, amplitudes, verdict, outputs, mitigation or +distribution of any kind; its `accuracy.class` is `none`; +and it has `stopped`, an object of exactly `at`, the string `max_joules`; `joules`, +what the reading had come to, a number at or above the ceiling; `max_joules`, the contract's; +`elapsed_ms`, a whole number and the result's `elapsed_ms`; and `read`, a sentence +saying what read it and the longest time between two reads, the first counted from +the start. Its `energy.joules_micro`, where it has one, is no less than `joules` × +10^6, less one for its rounding. It is sealed like any result, `energy` the whole +figure of the process killed where the host could read it, its `kept.energy` says the +ceiling was not kept, and a command line exits 4. A result whose energy was not read +whole states `kept.energy.joules` `null`. + +**The reasoning.** `planner` is an object of: + +| member | | +|---|---| +| `format` | `wai.quantum.planner/1` | +| `routes` | every route the host could see, an array with at least one member, each route's name once | +| `named` | the route the job names, or `null`: as below | +| `question` | the question the job asks, as below: `noise`, `counts`, `expectations` or `amplitudes` | +| `auto` | the route `auto` picks for this job, or `null`, as below | +| `wanted`, `wanted_from` | the class the routes are held to, and where it comes from, as below | +| `host` | `job_bytes`, the memory one job may take on the host, a whole number; `providers`, the names of the providers it brought, an array of strings: exactly the provider routes' names, in their order | +| `choice` | the name of the route chosen: a route of `routes` | +| `why` | a sentence | +| `stable` | below | +| `kept` | below | +| `shadow` | below: exactly when `choice` is a provider's | + +A route, an object of: + +| member | | +|---|---| +| `route` | its name: `method:`, or `provider:`, neither name empty | +| `kind` | `local` for a method, `provider` for a provider | +| `class` | a string: the class its result has at worst on this job. A built-in method's is held to the table below; a method a host registered that declares one class has that one, and one that declares several has the first of `bit-exact`, `exact`, `single`, `bounded`, `estimate` and `heuristic` that each of them meets (so `single` and `bounded` together are `heuristic`). A provider's route has the class its `provenance` gives (§8.4), and one that cannot run the job is `unknown` | +| `host_dependent` | `true` or `false`: whether the route depends on the host. A provider's, a method on a GPU (`statevector_single`, `cutrank_single`) and a method the host registered are, and no other built-in is | +| `auto_rank` | on a local route: its rank in `auto`'s order for the job's `question`, a whole number, or `null` where `auto` does not try it. A built-in method's is the table's below; a registered method's is the host's word | +| `price` | `null`, or an object: below | +| `outcome` | `chosen`, `met` or `rejected`. Exactly one route is `chosen`, and it is `choice` | +| `rejected` | exactly when `outcome` is `rejected`: `code`, one of the codes below, and `why`, a sentence | +| `approximate` | `true`, on a provider's route whose provider states its simulator is approximate | + +and a provider's route may name its `provider`, `device` and `provenance`, a +method's its `method`, as words a person reads. Where a provider's route names its +`provenance`, its class is the one that gives (§8.4), and where the route chosen names +its `device` or `provenance`, they are the result's provider's (`planner_choice`). + +The classes of the built-in methods, and which of them a route has on a job: + +| method | classes | a route's | +|---|---|---| +| `exact` | `bit-exact` | | +| `statevector`, `tensor_network`, `density_matrix` | `exact` | | +| `statevector_single`, `cutrank_single` | `single` | | +| `pauli`, `pulse` | `bounded` | | +| `trajectories` | `estimate` | | +| `mps` | `exact`, `heuristic` | either; a route says `heuristic`, since a run can be truncated, and a result not truncated says `exact` | +| `stabilizer` | `exact`, `estimate` | `estimate` where the request gives a `noise` or a device `target`, else `exact` | +| `stabilizer_rank` | `exact`, `estimate` | `estimate` where its `options` give `terms` or `epsilon`, else `exact` | +| `cutrank` | `exact`, `single` | either: the memory a job has chooses the precision of its table | + +Each is the class of the route listed in `routes`, priced or not, on a job that names +a provider as on any other: a shadow's class is its route's. The `accuracy.class` of a +result of a built-in method, and of a shadow's, is one of its method's; `contract_class` +and `shadow` hold them. + +A price, an object of: + +| member | | +|---|---| +| `money` | `free`: `true`, or `false` with `amount` and `currency` (strings, the amount as the provider gives it, at most 64 characters, with an optional `unit`), or `false` with `unknown`, a sentence. An unknown cost is not free (§7). A local route's is `free` `true`: only a provider's costs. `at_least`, absent or `true`: the amount is the least the job can come to, and what it takes decides the rest | +| `time` | `seconds`, a number from 0 to 10^12 or `null`; with a number, `basis`: `nominal`, at the engine's rate for the method's work, or `provider`, the provider's own estimate, queue included; with `null`, `why`. A host takes a provider's estimate past 10^12 seconds, or an amount past 64 characters, as no estimate: `null` here, `unknown` there, with why | +| `memory_bytes`, `work` | what a method takes, as whole numbers, a double past 2^53 − 1; `null`, and only `null`, on a provider's route | +| `energy` | `joules`, a number or `null`: an estimate of what the run takes, from past runs, with `basis`, and never a promise: a job's work leaves out what drives its time, and the same job read twice differs. With `null`, `why`. `watch`, a sentence, says what reads the run while it runs, and what that covers; with none, `unwatched`, a sentence, says why nothing can. A route has at most one of the two. A contract's `max_joules` is enforced by that reading, while the run goes (below): an estimate can only refuse a job clearly past a ceiling. No provider states a job's energy before it runs and no host reads one's run, so a provider's `joules` is `null` and it has no `watch` | +| `leaves_out` | what the price leaves out, an array of: `time`, it states no time; `amount`, it states no amount; `energy`, it states no energy; `mitigation`, what the provider's own mitigation costs or does, unless a client set it off or the device has none; `decoder`, any decoder's latency; `charged`, what the provider charges may differ from what it estimates; `cancel`, its client cannot stop a job it sent | +| `program` | on a provider's route, optional: the `shots`, `native_gates`, `two_qubit_gates` and `swaps` of what would be sent, and `expected_success` when a calibration states one | + +**What is named.** `named` is `provider:` the request's `provider`, where it gives +a string; else `method:` its `method`, where that is a string other than `auto`; +else, for a request that names a device `target`, the one method that target's +noise takes, a local route of `routes` (the host's word: the engine's own choice +for a target); else `null`. + +**The question** a job asks is read from its request alone: `noise` when it has a +`noise` other than `null`; else `counts` when its shots are above 0 (its `shots`, +a whole number written as one from 0 to 2^64 − 1, or, where it gives none or +another, 1024 when it gives no non-empty `observables` and no non-empty +`amplitudes`, and 0 otherwise); else `expectations` when it gives non-empty +`observables` and no non-empty `amplitudes`; else `amplitudes`. + +**What `auto` picks** is read from the routes: `null` when `named` is not `null`; +for a request whose `fabric` is neither absent, `null`, `auto` nor `cpu`, +`method:statevector` where that route's `price` is not `null`, else `null`; +otherwise the local route whose `price` is not `null` and whose `auto_rank` is +least, the first in `routes` of equal ranks, or `null` when there is none. Each +built-in method's rank, by question: + +| method | noise | counts | expectations | amplitudes | +|---|---|---|---|---| +| `exact` | | 20 | 20 | 10 | +| `statevector` | | 30 | 30 | 20 | +| `statevector_single` | | 40 | 40 | 30 | +| `stabilizer` | 20 | 10 | 10 | | +| `pauli` | | | 60 | | +| `mps` | | 60 | 70 | 70 | +| `stabilizer_rank` | | | 50 | 50 | +| `tensor_network` | | | | 60 | +| `cutrank` | | 50 | | 40 | +| `cutrank_single`, `pulse` | | | | | +| `density_matrix` | 10 | | | | +| `trajectories` | 30 | | | | + +(an empty cell is `null`). So what `auto` picks is what a verifier finds: a host +cannot lower the class a job keeps by naming a weaker route `auto`'s. Whether a +route has a price is the host's word, held to what the engine gives by +`--recheck` (below). + +**What is wanted.** `wanted` is the contract's `exactness` when it gives one, +with `wanted_from` `contract`. When it gives none, the job keeps what it would +have had: the class of the `named` route, with `wanted_from` `named`; when `named` +is `null`, the class of `auto`'s route, with `wanted_from` `auto`; and when `auto` +is `null` too, both are `null`. `named`, `question`, each built-in method's +`auto_rank`, `auto`, `wanted` and `wanted_from` must each be what these give. + +**Each route's outcome.** A verifier recomputes it from the request, the route and +`host.job_bytes`, by these rules in this order: the first that applies is the +route's `rejected.code`, and a route to which none applies is not rejected. + +1. `not_named`: `named` is not `null`, and this is not it. +2. `fabric`: `named` is `null`, and the request's `fabric` is neither absent, + `null` nor `auto`, and it is `cpu` and this is `method:statevector_single` or + `method:cutrank_single`, or it is anything else and this is not + `method:statevector`. +3. `cannot`: `class` is `unknown` and `price` is `null`. +4. `class`: `wanted` is not `null` and `class` does not meet it; or `wanted` is + `simulated`, the contract names it (`wanted_from` `contract`), and `approximate` + is `true`; or `wanted` is `null` and this is a provider's route. A contract + that names no class changes nothing a job already meets: an approximate + simulator the job names keeps its place. +5. `cannot`: `price` is `null`. +6. `memory`: `memory_bytes` is above `host.job_bytes`. +7. `providers`: this is a provider's route, and `contract.providers` is not + `allowed`. +8. `deadline_unknown`, `deadline`: the contract gives `deadline_seconds`, and + `time.seconds` is `null`, or above it. +9. For a provider's route whose `money.free` is not `true`: `cost_no_ceiling`, the + contract gives no `max_cost` and this is not the `named` route; + `cost_unknown`, it gives one and `money` has no `amount` that is an amount in + decimals, or no `currency`; `cost_currency`, the two currencies differ; + `cost`, the amount is above `max_cost.amount`; `cost_at_least`, `money.at_least` + is `true`, so what it will come to is not known to be within the ceiling. + Amounts are compared exactly, as decimals, with no double between them, and no + currency is converted. A + provider the request names, with no `max_cost`, meets this rule: its cost is + the person's to confirm (§7), as it is with no contract. +10. `energy_unwatched`, `energy`: the contract gives `max_joules`, and `energy` + has no `watch`, so nothing can stop the run at it; or `energy.joules` is above + it: an estimate past a ceiling refuses a job clearly over it, and one under it + promises nothing. + +So an unknown never passes where something is asked of it, and nothing falls back: +not from exact to approximate, since a less exact route does not meet `wanted`; not +from a simulator to a device or the reverse, since neither's class meets the +other's. A cost ceiling confirms nothing: a run that is not free still needs the +person's word for that run (§7). Where a host chose the provider (the request names +none), that word names what the person saw: a host gives the route, who it is (its +kind, device, provenance and description, and what the person's name for it stands +for: its endpoint, settings and credential's place), its estimate's `money`, the +program and shots it would send, the job's `contract`, and how many runs of this job +the host has sent on such a word before, as a short digest, and sends the job only when +the word it is given is that digest made again at send time; a route, a device, an +estimate, a program or a contract that changed since is not sent, and a word sends +one run: the next run of the same job has another word. The count is read and the run +recorded under one lock, so two sends of one word do not both go; a run the provider +took is a run whatever became of it, and only one it refused before taking it leaves +the word unspent. A job that names a provider under a contract that allows one but +wants a class no provider's counts have is refused (`J071`) before the provider is +asked anything. A host asks no provider +anything (an estimate's request carries the compiled program, and a description +says a job is coming) where the contract does not allow one, or names no class a +provider's counts are in: with none named the job keeps a classical class, which +no provider's meets. And a host holds its reasoning to these rules before it sends +anything, since a receipt it would refuse afterwards would be a run paid for and +lost. If no route is left, the job is refused (`J071`) with each route's reason, and +there is no result to seal. + +**The choice.** Of the routes these rules let through, the job runs the one this +picks, and `choice` names it: + +1. when the contract gives no `exactness` and `auto`'s route is let through, it + stands: a contract that names no class changes nothing a job already meets; +2. otherwise the least of them in this order: `money.free` `true` first, then an + `amount` in decimals (at most 64 characters), the lesser first, then any other; + a `time.seconds` before a `null`, and then the lesser of each `seconds` × 1000 + rounded to the nearest whole number, halves up (the floor of `seconds` × 1000 + + 0.5); `local` before `provider`; the lesser `memory_bytes`, a `null` read as 0; + and the name, by its UTF-8 bytes. + +`choice` must also be what ran: `method:` the result's `method`, or, when that is +`provider`, `provider:` its `provider.name`. + +**`stable`** says what is the same on every host. It is an object of `scope`, a +sentence; `routes`, the names of the routes whose `kind` is `local` and whose +`host_dependent` is `false`, in the order of `routes`; `digest`; and `choice`. + +- `digest` is the BLAKE3, as 64 lower-case hex digits, of the RFC 8785 text + (§8.2) of the object with `job_bytes`, `host.job_bytes`, and `routes`, an array + with one object for each of those routes in that order: `route`, `class`, and + `seconds`, `memory_bytes` and `work` from its price, each `null` when it has + none. It is the same for this request and `job_bytes` on every host of one + engine; a host that gives another has priced them otherwise, and a verifier that + holds the engine can price them again. +- `choice` is `true` exactly when `choice` names one of those routes, every route + with `host_dependent` `true` is rejected with `not_named`, `fabric` or `class`, + `contract.providers` is not `allowed`, and the contract gives no `max_joules`: + then the route chosen depends on nothing of the host. + +**`kept`** says what the contract asked, against what happened. It holds exactly a +member for each of these the contract gives, each of exactly the members its row +names (`max_cost` of exactly `amount` and `currency`). A result that missed one is still an +answer, and it says so: a `kept` of `false` breaks no rule. A host that can stop a +run stops it at its deadline (`J074`), and seals nothing. + +| member | | +|---|---| +| `deadline` | `seconds`, the contract's; `elapsed_ms`, a whole number or `null`: the result's `elapsed_ms` by value when its `method` is not `provider` and it states one; for a method's result that states none, so that its bits are the same on every host (a device target's, a pulse program's), the host's own time of the run; and for a provider's, the host's time from the job's submission to its counts; `kept`, whether `elapsed_ms` ≤ `seconds` × 1000, or `null` when `elapsed_ms` is `null` | +| `energy` | `max_joules`, the contract's; `joules`, the result's `stopped.joules`, else its `energy.joules_micro` ÷ 10^6, or `null` when it has neither; `kept`, `false` for a stopped run, else whether `joules` ≤ `max_joules`, or `null` when `joules` is `null` | +| `cost` | `max_cost`, the contract's; `charged`, equal to the result's `cost.charged` (numbers by value), or `null` when it has none; `kept`: with a `charged` in the ceiling's currency and an amount in decimals, whether it is at most the ceiling; with any other `charged`, `null`; with no `charged`, `true` when the result's `cost.free` is `true` or it has none, and otherwise `null` | + +**The class given.** The result's `accuracy.class` meets `wanted` when `wanted` is +not `null`, and a result whose `accuracy.approximate` is `true` does not meet a +`simulated` the contract names. A route whose result falls short of `wanted`, whether the contract +named it or the job keeps what it would have had, gives no answer (`J072`): a +host seals no result this rule refuses. + +**The shadow.** When a provider answers a contract job, a classical method that can +reach the same counts within the contract runs too. `planner.shadow` says which, +before anything runs, and the result's `shadow` carries what it gave. A shadow can +be run again by anyone; it is the one part of a provider's result that can. + +`planner.shadow` is an object with `route`, a method's route `method:`, or +`null`. With a route, which `routes` lists: `class`, a class of `bit-exact`, `exact`, +`single`, `bounded`, `estimate` and `heuristic`, and the one `routes` gives that route; +`budget_seconds`, what the contract leaves it: the +deadline less the chosen route's `time.seconds`, and 0 when that is more, the +deadline where it is `null`, and 300 with no deadline; `price`, a local route's +price, whose `time.seconds` is a number at most `budget_seconds`; and `request`, +an object of exactly `qasm`, the request's (a string); `shots`, the result's +(by value); `seed`, the request's `seed` (a whole number written as one, from 0 to +2^64 − 1, and 1 when it gives none or another) plus 2^32, modulo 2^53, a stream of +its own so that a seeded simulator's counts are not its counts by construction; +and `method`, what follows `method:` in `route`. No other member: a noise model or +any option would make the shadow another program. With `null`: `code`, one of +`budget`, `memory` and `none`; `why`, a sentence; and optionally `tried`, an array, +each method's own. + +A result's `shadow` is one of: + +- `ran` `false`, with `code`, a string, and `why`, a sentence: when `planner.shadow` + has no `route`, `code` is its `code`; otherwise `failed`, the method's run did not + complete. The provider's answer stands, alone, and says so; `--recheck` runs the + planned shadow, and a host whose failed shadow runs there is found. +- `ran` `true`, where `planner.shadow` has a route: with `route` and `request`, + equal to those of `planner.shadow` (numbers by value); `shots`, the result's; + `accuracy`, an object whose `class` is a string that meets `planner.shadow.class` + and is one of its method's; `counts`, keyed by outcomes all as long as the + provider's counts' (where they list one) and each of `0` and `1` only, each a whole number written as one from 1 to 2^53 − 1, and + `omitted_shots`, a whole number of at least 0 by value, which sum exactly to the + result's `shots` (a whole number by value); `distinct_outcomes`, a whole number + of at least 0, and, with no shot omitted, the number of outcomes listed; optionally + `elapsed_ms`; and `distance`. + +`distance` is an object. With `computed` `false`, it has `why`, and it is `false` +only when the provider's or the shadow's `omitted_shots` is not 0 (by value: `0` +however it is written is 0). Otherwise it is `computed` `true` and, with a_k and b_k +the provider's and the shadow's count of each outcome k in either, S the result's +`shots` read as a whole number from 0 to 2^64 − 1 (its double's whole part, and +2^64 − 1 past it), and the outcomes taken in the order of their UTF-8 bytes: + +- `numerator`, the sum of |a_k − b_k|, and `denominator`, 2·S, whole numbers, + each exact and written as a double past 2^53 − 1; +- `total_variation`, `numerator` ÷ `denominator`; +- `hellinger_fidelity`, R·R ÷ (S·S), with R the sum, in that order, of √(a_k × b_k), + each count taken as a double and the product a double's; +- `sampling_tvd_bound`, the lesser of 1 and 0.5·F ÷ S, with F the sum, in that + order, of m(a_k + b_k): a bound on the total variation these shots alone would + leave between two samples of one distribution, on average, for every number of + outcomes and shots. m(n) is what a fair coin's split of n leaves between its two + sides on average, E|2B − n| with B binomial (n, ½): 0 for n = 0; for n = 2j + 1 + or 2j + 2 with j < 4096, the product, from 1 and in that order, of (2i + 3) ÷ + (2i + 2) for i from 0 to j − 1; and from j = 4096, (2j + 1) × c with c = (1 − + 1 ÷ (8j) + 1 ÷ (128·j·j) + 5 ÷ (1024·j·j·j)) ÷ √(π·j), each term as written. Given + how many shots of each outcome the two lists hold together, two lists of S shots + each split them at least as tightly as the coin does, so F ÷ 2S is at least the + expected total variation. + +A count is a whole number written as one (no fraction, no exponent) from 0 to +2^64 − 1, and 0 when it is anything else or absent. S of 0, or counts that sum to +more than 2·S, gives no distance, and a `distance` that states one then does not +hold. Each double is IEEE 754, rounded to nearest, computed in the order +written, so that every verifier gets the same bits. + +**Reasons.** A verifier reports each of these that applies, beside those of §8.4: + +| reason | when | +|---|---| +| `contract_form` | the request's `contract` is not of its form (of §8.7, then reported alone); or, under a contract, a provider's result of the earlier form (§8.4), which states neither where its counts come from nor what was done to them | +| `contract_provider` | the request names a `provider` and its contract's `providers` is not `allowed` | +| `planner_form` | a contract job's result has no `planner`, or one not of the form above: `format`, `routes` and each route's members (a local route's `auto_rank`, its money free, every `seconds` and amount within its bounds), `named`, `auto` and `choice` each naming a route of `routes` or `null` (`choice` a route), `question`, `host`, `why`, `stable` and `kept` an object, each present; or `named`, `question`, a built-in method's `auto_rank`, `auto`, `wanted` or `wanted_from` is not what the request and the routes give. Or a result with no contract carries a `planner`. Reported alone of §8.7, beside `contract_provider` | +| `planner_route` | a route's `rejected.code` is not what the rules above give it (or it is rejected when they let it through, or not when they do not), or the route `chosen` is not one and `choice` | +| `planner_choice` | `choice` is not the route the choice's rules pick from those the rules let through, whatever their `outcome` says; or it is not what ran: a method's result is of another method, and a provider's names another provider, or its `cost` is not its route's `money` (`free` alike, and `amount`, `currency`, `unit` and `at_least` in its `estimate` alike), or the route names a `device` or `provenance` that is not its provider's. Members are alike as numbers are by value (`7` and `7.0`, `-0` and `0`), a boolean only to a boolean, and `null` as an absent member | +| `planner_stable` | `stable.routes`, `digest` or `choice` is not what the routes give | +| `stopped` | the result's `stopped` is not of its form above, or is on a job whose contract gives no `max_joules` | +| `planner_kept` | `kept` does not hold exactly a member for each the contract gives, or any of those members is not what the table gives | +| `contract_class` | the result's class does not meet `wanted` | +| `shadow` | `planner.shadow` or the result's `shadow` is missing when `choice` is a provider's, or present when it is not; or `planner.shadow` is not of its form above (its route, class, budget, price and request), or the result's `shadow` is not of its form, its `request` is not what `planner.shadow` gives, its counts do not sum to the shots, its class does not meet the plan's, or its `distance` is not what its counts give. Or a result with no contract carries a `shadow` | + +A verifier also states, for a contract job, its `choice`, `wanted`, the class given, +`stable.choice`, `kept`, whether its shadow ran, and its `total_variation`. A price +is the host's word, as everything it says it received, sent and checked is (§8.5): +what a verifier recomputes is what follows from it. A verifier that holds the engine +can price the routes again and run the shadow again +(`wai-quantum verify --recheck`), which holds `digest`, `named` and `auto` to what +this engine gives (`auto` over the routes that depend on the host as the host stated +them: a verifier here has neither its GPU nor its registered methods); holds the +shadow's counts and class to a run here; runs a shadow the host says failed; and, +on the same engine, plans the shadow again, so that which method ran, or that none +could, is what this engine gives: a verifier without one takes those on the host's +word. A receipt sealed by another engine whose shadow did not run is held neither +way: what this engine plans is said, and the recheck does not say it holds. So is any +receipt sealed by another engine version: a recheck there gives `holds` `null` unless +something differs. + +The free job service reaches no provider. It lists none among its routes, a +contract that wants a device's class is refused there (`J071`), and a request that +names a provider is refused there as it always is (`J002`). + ## 9. Conformance `wai-quantum-qpu/conformance/provider-v1.json` holds the vectors: @@ -716,7 +1135,8 @@ by the device. It states its counts' source and its `execution` (§5.5). **Receipts.** `quantum-conformance/receipts/` holds job receipts and what a verifier must say of each (§8.4): receipts made by the command line on this machine and by the job service, provider jobs of every built-in kind through -services that follow their contracts, the earlier form, the first (receipts the +services that follow their contracts, jobs under a contract (§8.7), the earlier +form, the first (receipts the first form's own writer sealed, and others `generate.py` made from §8.2's text), and receipts sealed to break one rule each. A receipt from a person's account names that account, and is not published: it is @@ -748,5 +1168,6 @@ A result's receipt seals every member it holds, so a member a later text adds to the result is in no receipt sealed before it, and every such receipt verifies as it did (§8.4's earlier form). `counts_source`, `execution`, `compiled.qasm3`, the class `simulated` and `accuracy.approximate` were added -so, as were the answers' `counts_source` and `execution` and `describe`'s -`approximate`. +so, as were the answers' `counts_source` and `execution`, `describe`'s +`approximate`, and a request's `contract` with a result's `planner` and `shadow` +(§8.7): a receipt of a request with no contract verifies as it did. diff --git a/wai/quantum-conformance/receipts/README.md b/wai/quantum-conformance/receipts/README.md index 605f35a8e..b41fa9885 100644 --- a/wai/quantum-conformance/receipts/README.md +++ b/wai/quantum-conformance/receipts/README.md @@ -7,9 +7,9 @@ exactly the reasons the manifest names (§8.4): none for a valid one. | file | what | |---|---| | `manifest.json` | every receipt in `jobs/`, the reasons a verifier must give it, how it was made, and what it is. Every expectation is written by hand from §8.4; none is copied from a verifier's output | -| `jobs/cli-*.json` | made by the command line on this machine, sealed with the published demo key (`make.sh`): runs by several methods, a compile, and runs on the reference provider over a local process, free and priced | +| `jobs/cli-*.json` | made by the command line on this machine, sealed with the published demo key (`make.sh`): runs by several methods, a compile, runs on the reference provider over a local process, free and priced, and jobs under a contract (§8.7), here, routed to the person's providers and on a provider named under a ceiling | | `jobs/service-*.json` | made by the free job service, sealed with its key (`make.sh`) | -| `jobs/scripted-*.json` | provider jobs of every built-in kind (`sampler-v2`, `prx-circuits`, `native-turns` with and without a noise model, `cloud-tasks` on a processor and on its simulator, with rows of shots and with probabilities), each through a service that follows that provider's published contract, sealed with the demo key (`wai-quantum-qpu/tests/clients.rs`, `every_built_in_kind_states_what_it_sent_and_its_receipt_keeps_every_rule`, with `WAI_QUANTUM_RECEIPT_CORPUS` set to this directory) | +| `jobs/scripted-*.json` | provider jobs of every built-in kind (`sampler-v2`, `prx-circuits`, `native-turns` with and without a noise model, `cloud-tasks` on a processor and on its simulator, with rows of shots and with probabilities), each through a service that follows that provider's published contract, sealed with the demo key (`wai-quantum-qpu/tests/clients.rs`, `every_built_in_kind_states_what_it_sent_and_its_receipt_keeps_every_rule`, with `WAI_QUANTUM_RECEIPT_CORPUS` set to this directory); and `prx-circuits` under a contract, its device's counts with a classical method's beside them (`a_built_in_kind_runs_under_a_contract_and_a_classical_method_shadows_it`) | | `jobs/first-form-*.json` | sealed by the job service as it was on 18 October 2026 (commit 72d18742d), so by the first form's own writer, not by a restatement of it | | `jobs/fixture-*.json` | the engine's pinned fixtures, sealed by earlier engines: a run before results named their engine, a provider job of the earlier form, and a compile | | `jobs/crafted-*.json` | made by `generate.py` from the receipts above, each changed one way: the seal's form, the strict signature (a weak-key forgery, `S + ℓ`, a mixed-order key, …), the first form, what any JSON reader and writer may do (and so must change nothing), the strict reader, and each rule of a provider's result, each sealed again with the demo key where the change is inside the seal so that one rule alone breaks | @@ -55,7 +55,8 @@ says and not only by its digest. `--plant NAME` runs the second verifier with a defect planted in it: a lenient key check, `alg` unchecked, the last of a member named twice kept, inexact numbers let through, a simulator's counts let pass as measured, a ceiling on every whole number, `R` of small order -let through. The differential succeeds only when it catches the plant. That is the proof that +let through, and under a contract (§8.7) each route's outcome, the planner's choice or a +shadow's distance taken as it stands. The differential succeeds only when it catches the plant. That is the proof that it can fail. `--extra DIR` adds receipts a person holds and does not publish: both verifiers must find each @@ -73,7 +74,7 @@ the manifest, with its plants, among the independent verifiers ```sh bash receipts/make.sh PATH/wai-quantum receipts/jobs # the command line's and the service's (cd ../wai-quantum-qpu && WAI_QUANTUM_RECEIPT_CORPUS=$PWD/../quantum-conformance/receipts/jobs \ - cargo test --test clients every_built_in_kind) # the built-in kinds' + cargo test --test clients -- every_built_in_kind a_built_in_kind_runs_under_a_contract) # the built-in kinds' python3 -I receipts/generate.py # the crafted half and the manifest ``` diff --git a/wai/quantum-conformance/receipts/generate.py b/wai/quantum-conformance/receipts/generate.py index 3d231398a..806ecbb4b 100644 --- a/wai/quantum-conformance/receipts/generate.py +++ b/wai/quantum-conformance/receipts/generate.py @@ -28,6 +28,7 @@ import copy import hashlib import importlib.util import json +import math import os import struct import sys @@ -302,6 +303,21 @@ def seal_set(body, seed=DEMO): return out +def coin_split(n): + """Section 8.7's m(n): what a fair coin's split of n leaves between its sides on average.""" + if n == 0: + return 0.0 + j = (n - 1) // 2 + if j < 4096: + m = 1.0 + for i in range(j): + m = m * float(2 * i + 3) / float(2 * i + 2) + return m + jj = float(j) + c = (1.0 - 1.0 / (8.0 * jj) + 1.0 / (128.0 * jj * jj) + 5.0 / (1024.0 * jj * jj * jj)) / math.sqrt(math.pi * jj) + return (2.0 * jj + 1.0) * c + + def edited(body, edit, form="canonical"): """body changed by edit (which may change request, result or both), sealed again.""" b = copy.deepcopy(body) @@ -700,6 +716,293 @@ def cases(): add("method-measured", edited(run, at(R + ("accuracy", "class"), "measured")), ["provider_class"], "the engine's own result labelled measured") add("method-simulated", edited(run, at(R + ("accuracy", "class"), "simulated")), ["provider_class"], "the engine's own result labelled simulated") add("method-class-unknown", edited(run, at(R + ("accuracy", "class"), "quasi-exact")), [], "a class a verifier does not know: not a reason, since a later version may add one") + out.extend(contract_cases(run, at, drop)) + return out + + +def contract_cases(run, at, drop): + """Section 8.7: a job under a contract, each rule broken once and sealed again, and + what a host may state and still be valid. Each expectation is written from 8.7.""" + local = load("cli-contract-local.json") + auto = load("cli-contract-auto.json") + routed = load("cli-contract-routed.json") + named = load("cli-contract-provider-priced.json") + out = [] + + def add(name, body, reasons, what): + out.append(("crafted-contract-" + name + ".json", dump(body) + "\n", sorted(reasons), what)) + + R, P = ("result",), ("result", "planner") + + def route(name, f): + def g(b): + f(next(r for r in b["result"]["planner"]["routes"] if r["route"] == name)) + return g + + def both(*fs): + def g(b): + for f in fs: + f(b) + return g + + def met(r): + r["outcome"] = "met" + r.pop("rejected", None) + + # --- the contract and the reasoning's form + add("form-member", edited(local, at(("request", "contract", "deadline"), 1)), ["contract_form"], "a member no contract has: read as absent, a requirement would drop in silence") + add("form-exactness", edited(local, at(("request", "contract", "exactness"), "nearly")), ["contract_form"], "an exactness that is no class") + add("form-cost", edited(local, at(("request", "contract", "max_cost", "amount"), "1e3")), ["contract_form"], "a ceiling's amount that is not in decimals") + add("form-cost-long", edited(local, at(("request", "contract", "max_cost", "amount"), "1" * 65)), ["contract_form"], "a ceiling's amount of 65 characters: at most 64") + add("planner-missing", edited(local, drop(P)), ["planner_form"], "a contract job sealed without its reasoning") + add("planner-format", edited(local, at(P + ("format",), "wai.quantum.planner/2")), ["planner_form"], "a reasoning of another format") + add("planner-wanted", edited(local, at(P + ("wanted",), "heuristic")), ["planner_form"], "a class wanted that is not the contract's") + add("planner-wanted-from", edited(auto, at(P + ("wanted_from",), "contract")), ["planner_form"], "a class said to be the contract's, where the contract names none and the job keeps auto's") + add("planner-on-plain", edited(run, at(R + ("planner",), local["result"]["planner"])), ["planner_form"], "a job with no contract that carries a reasoning") + add("shadow-on-plain", edited(run, at(R + ("shadow",), {"ran": False, "code": "none", "why": "no provider answered"})), ["shadow"], "a job with no contract that carries a shadow") + # --- each route's outcome and the choice, recomputed + add("route-claimed", edited(local, route("method:mps", met)), ["planner_route"], "a heuristic route said to meet exact") + add("route-code", edited(local, route("method:mps", lambda r: r["rejected"].update(code="deadline"))), ["planner_route"], "a route rejected for a reason the rules do not give it") + + def dearer(b): + route("method:stabilizer", lambda r: r.update(outcome="met"))(b) + route("method:statevector", lambda r: r.update(outcome="chosen"))(b) + b["result"]["planner"]["choice"] = "method:statevector" + b["result"]["method"] = "statevector" + add("choice-dearer", edited(local, dearer), ["planner_choice"], "another route that meets the contract chosen and run, where the rule picks the cheaper") + add("choice-not-run", edited(local, at(R + ("method",), "statevector")), ["planner_choice"], "the route chosen is not what ran") + add("stable-digest", edited(local, at(P + ("stable", "digest"), "00" * 32)), ["planner_stable"], "a digest that is not what the routes' prices give") + add("stable-choice", edited(local, at(P + ("stable", "choice"), False)), ["planner_stable"], "a choice said to depend on the host, where it depends on nothing of it") + add("route-price-work", edited(local, route("method:stabilizer", lambda r: r["price"].update(work=r["price"]["work"] + 1))), ["planner_stable"], "a price changed that the digest covers and the order does not: the rule still picks the route") + add("route-price-memory", edited(local, route("method:stabilizer", lambda r: r["price"].update(memory_bytes=1 << 29))), ["planner_choice", "planner_stable"], "a price changed that the digest covers and the order reads: another route that meets the contract now comes first") + # --- what the contract kept, and the class given + add("kept-false", edited(local, at(P + ("kept", "deadline", "kept"), False)), ["planner_kept"], "a deadline said missed that was kept") + add("kept-dropped", edited(local, drop(P + ("kept", "cost"))), ["planner_kept"], "a ceiling the contract gives, and kept does not state") + + def late(b): + b["result"]["elapsed_ms"] = 61000 + b["result"]["planner"]["kept"]["deadline"]["elapsed_ms"] = 61000 + b["result"]["planner"]["kept"]["deadline"]["kept"] = False + add("kept-missed-stated", edited(local, late), [], "a deadline missed and said so: an answer all the same, and valid") + add("class-short", edited(local, at(R + ("accuracy", "class"), "estimate")), ["contract_class"], "a result whose class does not meet the class wanted") + add("shadow-on-local", edited(local, at(R + ("shadow",), {"ran": False, "code": "none", "why": "no provider answered"})), ["shadow"], "a local route's result that carries a shadow") + # --- a provider's answer and its shadow + S = R + ("shadow",) + add("shadow-missing", edited(routed, drop(S)), ["shadow"], "a provider's answer without its shadow") + add("shadow-plan-missing", edited(routed, drop(P + ("shadow",))), ["shadow"], "a provider's answer whose reasoning planned no shadow") + add("shadow-numerator", edited(routed, lambda b: b["result"]["shadow"]["distance"].update(numerator=b["result"]["shadow"]["distance"]["numerator"] + 1)), ["shadow"], "a distance that is not what the two lists of counts give") + add("shadow-not-computed", edited(routed, at(S + ("distance",), {"computed": False, "why": "said so"})), ["shadow"], "a distance not computed, with every shot listed on both sides") + + def reseeded(b): + for p in (b["result"]["shadow"]["request"], b["result"]["planner"]["shadow"]["request"]): + p["seed"] = 4 + add("shadow-seed", edited(routed, reseeded), ["shadow"], "a shadow sampled on the job's own stream, not one of its own") + add("shadow-said-none", edited(routed, at(S, {"ran": False, "code": "none", "why": "said none"})), ["shadow"], "a shadow said not to have run, where its plan had a route") + add("shadow-omitted-spelt", edited(routed, at(S + ("omitted_shots",), 0.0)), [], "a shadow's omitted_shots of 0 written as 0.0: 0 by value, and valid") + add("route-provider-claimed", edited(routed, route("provider:priced", met)), ["planner_route"], "a provider that costs money, with no ceiling to hold it to, said to meet the contract") + add("provider-not-chosen", edited(routed, at(R + ("provider", "name"), "priced")), ["planner_choice", "request_provider"], "an answer from a provider the planner did not choose") + add("providers-not-allowed", edited(routed, drop(("request", "contract", "providers"))), ["planner_choice", "planner_route", "request_provider"], "a provider's answer to a contract that does not allow one") + add("at-least-false", edited(routed, route("provider:priced", lambda r: r["price"]["money"].update(at_least=False))), ["planner_form"], "at_least given and not true") + add("at-least-claimed", edited(named, route("provider:priced", lambda r: r["price"]["money"].update(at_least=True))), ["planner_choice", "planner_route"], "a cost that is the least it can come to, under the ceiling, said to meet it") + def charged_over(b): + b["result"]["cost"]["charged"]["amount"] = "1.5" + b["result"]["planner"]["kept"]["cost"]["charged"]["amount"] = "1.5" + add("charged-over", edited(named, charged_over), ["planner_kept"], "charged past the ceiling, and kept said to hold") + + def over(b): + charged_over(b) + b["result"]["planner"]["kept"]["cost"]["kept"] = False + add("charged-over-stated", edited(named, over), [], "charged past the ceiling, and said so: valid") + add("kept-charged-other", edited(named, at(P + ("kept", "cost", "charged", "amount"), "0.01")), ["planner_kept"], "kept stating a charge that is not the result's: within the ceiling, and not what was charged") + add("kept-member-extra", edited(local, at(P + ("kept", "deadline", "note"), "on time")), ["planner_kept"], "a member of kept that its table does not give") + add("kept-elapsed-other", edited(local, lambda b: b["result"]["planner"]["kept"]["deadline"].update(elapsed_ms=b["result"]["elapsed_ms"] + 1)), ["planner_kept"], "a method's time in kept that is not the run's own elapsed_ms, within the deadline all the same") + + # --- what the job names, the question it asks, and what auto picks (review: auto verifiable) + add("auto-other", edited(auto, at(P + ("auto",), "method:statevector")), ["planner_form"], "auto said to pick a route the ranks do not") + add("auto-rank-lowered", edited(auto, route("method:statevector", lambda r: r.update(auto_rank=5))), ["planner_form"], "a route's rank in auto's order lowered, so that auto would pick it") + add("auto-rank-other", edited(auto, route("method:mps", lambda r: r.update(auto_rank=65))), ["planner_form"], "a rank that is not the method's, on a route that does not win by it") + add("auto-rank-missing", edited(auto, route("method:statevector", lambda r: r.pop("auto_rank"))), ["planner_form"], "a local route without its rank in auto's order") + add("question-other", edited(auto, at(P + ("question",), "amplitudes")), ["planner_form"], "a question the request does not ask") + add("named-other", edited(named, at(P + ("named",), None)), ["planner_form"], "a provider the request names, said to be named by nothing") + # --- a provider under a contract (review: providers default to never, J070) + add("provider-named-not-allowed", edited(named, drop(("request", "contract", "providers"))), ["contract_provider", "planner_choice", "planner_route"], "a provider named under a contract that does not allow one: never is the default") + add("named-approximate", edited(named, route("provider:priced", lambda r: r.update(approximate=True))), [], "a provider named, its simulator stated approximate, under a contract that names no class: it keeps the named route's class, and the rule against an approximate simulator holds only a class the contract names") + add("approximate-rejected", edited(routed, route("provider:priced", lambda r: (r.update(approximate=True), r["rejected"].update(code="class")))), [], "a simulator stated approximate, where the contract wants simulated: rejected for its class, before its cost is weighed") + # --- the bounds of a price (review: seconds and amounts a verifier reads whole) + add("price-seconds-past", edited(routed, route("provider:priced", lambda r: r["price"]["time"].update(seconds=1e13))), ["planner_form"], "a time past 10^12 seconds, which a host states as unknown") + add("price-amount-long", edited(routed, route("provider:priced", lambda r: r["price"]["money"].update(amount="1" * 65))), ["planner_form"], "an amount of 65 characters, which a host states as unknown") + add("local-money", edited(local, route("method:statevector", lambda r: r["price"].update(money={"free": False, "amount": "0", "currency": "USD"}))), ["planner_form"], "a method here priced in money: a local route is free") + # --- the rules' edges, each a route's code the rule gives it + sv_bytes = lambda b: b["result"]["planner"]["host"]["job_bytes"] + add("memory-at-cap", edited(local, lambda b: route("method:statevector", lambda r: r["price"].update(memory_bytes=sv_bytes(b)))(b)), ["planner_stable"], "a route that needs exactly the job's memory meets it; the digest covers memory, and is not the routes' now") + + def unknown_time(r): + r["price"]["time"] = {"seconds": None, "why": "said unknown"} + r["outcome"] = "rejected" + r["rejected"] = {"code": "deadline_unknown", "why": "its time is not known, and the contract gives a deadline"} + add("deadline-unknown", edited(local, route("method:cutrank", unknown_time)), ["planner_stable"], "a route whose time is unknown under a deadline, rejected for it; the digest covers the time, and is not the routes' now") + + def currency(b): + b["request"]["contract"]["max_cost"]["currency"] = "EUR" + add("currency-other", edited(named, currency), ["planner_choice", "planner_kept", "planner_route"], "a ceiling in another currency than the estimate's: no route meets it, and kept states another ceiling") + + def joules(b): + b["request"]["contract"]["max_joules"] = 2 + for r in b["result"]["planner"]["routes"]: + if r["price"] is not None: + r["price"]["energy"] = {"joules": 1.5, "basis": "an estimate", "watch": "a host's live reading"} + b["result"]["energy"] = {"joules_micro": 2000000} + b["result"]["planner"]["kept"]["energy"] = {"max_joules": 2, "joules": 2, "kept": True} + b["result"]["planner"]["stable"]["choice"] = False + add("energy-at-ceiling", edited(local, joules), [], "an energy ceiling met exactly by a figure sealed after the run, every route watched: kept, and the choice depends on the host") + add("energy-stable-claimed", edited(local, both(joules, at(P + ("stable", "choice"), True))), ["planner_stable"], "the same, the choice said to depend on nothing of the host") + + def unwatched(outcome, code=None): + def f(r): + r["price"]["energy"] = {"joules": 0.5, "basis": "an estimate", "unwatched": "nothing reads it"} + r["outcome"] = outcome + r.pop("rejected", None) + if code: + r["rejected"] = {"code": code, "why": "said so"} + return f + add("energy-unwatched", edited(local, both(joules, route("method:statevector", unwatched("rejected", "energy_unwatched")))), [], "a route nothing can read while it runs, under a ceiling: refused, though its estimate is under it") + add("energy-unwatched-claimed", edited(local, both(joules, route("method:statevector", unwatched("met")))), ["planner_route"], "a route nothing can stop, said to meet a ceiling") + add("energy-over-estimate", edited(local, both(joules, route("method:statevector", lambda r: (r["price"]["energy"].update(joules=3), r.update(outcome="rejected"), r.update(rejected={"code": "energy", "why": "said so"}))))), [], "an estimate clearly past the ceiling refuses a watched route") + add("energy-estimate-at-ceiling", edited(local, both(joules, route("method:statevector", lambda r: r["price"]["energy"].update(joules=2)))), [], "an estimate exactly at the ceiling is not past it, and refuses nothing") + add("energy-watch-form", edited(local, both(joules, route("method:statevector", lambda r: r["price"]["energy"].update(watch=True)))), ["planner_form"], "a watch that is no sentence") + + def stopped(b): + joules(b) + for k in ("counts", "distinct_outcomes", "omitted_shots", "outcome_dimension"): + b["result"].pop(k, None) + b["result"]["accuracy"] = {"class": "none", "note": "stopped at its ceiling"} + b["result"]["stopped"] = {"at": "max_joules", "joules": 2.5, "max_joules": 2, "elapsed_ms": 0, "read": "a host's live reading"} + b["result"]["elapsed_ms"] = 0 + b["result"]["energy"] = {"unmetered": "stopped"} + b["result"]["planner"]["kept"]["energy"] = {"max_joules": 2, "joules": 2.5, "kept": False} + add("stopped", edited(local, stopped), [], "a run stopped at its ceiling by a live reading: no answer, and a receipt that says so") + add("stopped-kept-claimed", edited(local, both(stopped, at(P + ("kept", "energy", "kept"), True))), ["planner_kept"], "a stopped run said to have kept its ceiling") + add("stopped-under", edited(local, both(stopped, at(R + ("stopped", "joules"), 1.5), at(P + ("kept", "energy", "joules"), 1.5))), ["stopped"], "a run said stopped under its ceiling") + add("stopped-with-counts", edited(local, both(stopped, at(R + ("counts",), {"00": 100}))), ["stopped"], "a stopped run that gives an answer") + add("stopped-whole-below", edited(local, both(stopped, at(R + ("energy",), {"joules_micro": 1}))), ["stopped"], "a stopped run whose whole figure is less than what stopped it") + add("stopped-whole-above", edited(local, both(stopped, at(R + ("energy",), {"joules_micro": 2600000}))), [], "a stopped run whose whole figure is a little past what stopped it") + add("stopped-elapsed-fraction", edited(local, both(stopped, at(R + ("stopped", "elapsed_ms"), 1.5), at(R + ("elapsed_ms",), 1.5), at(P + ("kept", "deadline", "elapsed_ms"), 1.5))), ["planner_kept", "stopped"], "a stop at a time that is no whole number, the result's the same (a deadline's kept time is whole too)") + add("stopped-elapsed-other", edited(local, both(stopped, at(R + ("stopped", "elapsed_ms"), 99999))), ["stopped"], "a stop at another time than the result's") + add("stopped-with-verdict", edited(local, both(stopped, at(R + ("verdict",), {"holds": True}))), ["stopped"], "a stopped run that gives a verdict, an answer by another name") + add("stopped-with-outputs", edited(local, both(stopped, at(R + ("outputs",), {"x": 1}))), ["stopped"], "a stopped run that gives outputs") + add("stopped-other-ceiling", edited(local, both(stopped, at(R + ("stopped", "max_joules"), 9))), ["stopped"], "a stop at a ceiling the contract does not give") + add("stopped-at-ceiling", edited(local, both(stopped, at(R + ("stopped", "joules"), 2), at(P + ("kept", "energy", "joules"), 2))), [], "a reading exactly at the ceiling stops a run") + add("stopped-class", edited(local, both(stopped, at(R + ("accuracy", "class"), "exact"))), ["stopped"], "a stopped run that claims a class") + add("stopped-on-provider", edited(local, both(stopped, at(R + ("method",), "provider"))), ["contract_form", "counts", "planner_choice", "provider_class", "request_provider", "request_shots", "stopped"], "a stop on a provider's run, which nothing here reads: and a local job's request and route, which no provider's result can have, in the earlier form") + add("stopped-read-form", edited(local, both(stopped, at(R + ("stopped", "read"), 7))), ["stopped"], "a stop that does not say what read it") + add("stopped-elapsed-form", edited(local, both(stopped, at(R + ("stopped", "elapsed_ms"), 1.5))), ["stopped"], "a stop at a time that is no whole number") + add("stopped-extra-member", edited(local, both(stopped, at(R + ("stopped", "note"), "more"))), ["stopped"], "a stop with a member its form does not have") + add("stopped-at-other", edited(local, both(stopped, at(R + ("stopped", "at"), "deadline"))), ["stopped"], "a stop at something other than the energy ceiling") + add("energy-watch-both", edited(local, both(joules, route("method:statevector", lambda r: r["price"]["energy"].update(unwatched="and yet")))), ["planner_form"], "a route said both to be read and to have no reading") + add("stopped-on-plain", edited(run, at(R + ("stopped",), {"at": "max_joules"})), ["stopped"], "a job with no contract said to have been stopped") + + # --- what a route states of itself (the verification of the review) + add("route-class-gpu", edited(local, route("method:statevector_single", lambda r: r.update({"class": "exact"}))), ["planner_route"], "the GPU's single precision stated exact: a class its method does not have") + add("route-class-by-job", edited(routed, route("method:stabilizer", lambda r: r.update({"class": "estimate"}))), ["planner_route", "planner_stable"], "the stabilizer stated estimate, on a job with no noise and no target") + add("route-host-dependent", edited(local, route("method:trajectories", lambda r: r.update(host_dependent=True))), ["planner_route", "planner_stable"], "a built-in on no GPU said to depend on the host, which takes it out of the digest") + add("route-provider-host-independent", edited(routed, route("provider:priced", lambda r: r.update(host_dependent=False))), ["planner_route"], "a provider's route said not to depend on the host") + add("result-class-foreign", edited(local, at(R + ("accuracy", "class"), "bit-exact")), ["contract_class"], "the stabilizer's result stated bit-exact: it meets what is wanted, and its method has no such class") + add("price-memory-null", edited(local, route("method:statevector", lambda r: r["price"].update(memory_bytes=None))), ["planner_form"], "a method's memory stated null, which passes the memory rule and wins its tie") + add("price-provider-memory", edited(routed, route("provider:priced", lambda r: r["price"].update(memory_bytes=1024))), ["planner_form"], "a provider's route stating a memory") + add("host-providers-other", edited(routed, at(P + ("host", "providers"), ["someone-else"])), ["planner_form"], "host.providers that are not the provider routes") + # --- the shadow, a method's run of exactly the job's program (review: steered, suppressed, unverifiable) + add("shadow-route-missing", edited(routed, drop(S + ("route",))), ["shadow"], "a shadow that names no route") + add("shadow-plan-route-missing", edited(routed, drop(P + ("shadow", "route"))), ["shadow"], "a shadow planned with no route, where null would say why") + add("shadow-plan-route-absent", edited(routed, both(at(P + ("shadow",), {"code": "none", "why": "said none"}), at(S, {"ran": False, "code": "none", "why": "said none"}))), ["shadow"], "a plan with neither a route nor null, and a shadow said not to have run") + + def provider_shadow(b): + for side in (b["result"]["planner"]["shadow"], b["result"]["shadow"]): + side["route"] = "provider:ref" + side["request"].pop("method") + add("shadow-route-provider", edited(routed, provider_shadow), ["shadow"], "a provider as its own shadow") + + def noisy(b): + for side in (b["result"]["planner"]["shadow"], b["result"]["shadow"]): + side["request"]["noise"] = {"depolarizing_2q": 0.2} + add("shadow-request-extra", edited(routed, noisy), ["shadow"], "a shadow run under a noise model the job never asked for, on both sides") + add("shadow-plan-code", edited(routed, both(at(P + ("shadow",), {"route": None, "code": "failed", "why": "said so"}), at(S, {"ran": False, "code": "failed", "why": "said so"}))), ["shadow"], "a shadow planned with a code no plan has") + add("shadow-plan-class", edited(routed, at(P + ("shadow", "class"), "heuristic")), ["shadow"], "a shadow planned at a class its route is not listed with") + add("shadow-plan-budget", edited(routed, at(P + ("shadow", "budget_seconds"), 299)), ["shadow"], "a budget that is not what the contract leaves") + add("shadow-plan-price-over", edited(routed, at(P + ("shadow", "price", "time", "seconds"), 301)), ["shadow"], "a shadow planned at a time past its budget") + + def fraction(b): + c = b["result"]["shadow"]["counts"] + k = sorted(c)[0] + c[k] = c[k] - 0.5 + c[sorted(c)[1]] += 0.5 + add("shadow-count-fraction", edited(routed, fraction), ["shadow"], "a shadow's counts that are not whole, summing to the shots all the same") + add("shadow-count-sum", edited(routed, lambda b: b["result"]["shadow"]["counts"].update({sorted(b["result"]["shadow"]["counts"])[0]: b["result"]["shadow"]["counts"][sorted(b["result"]["shadow"]["counts"])[0]] + 1})), ["shadow"], "a shadow's counts that sum to more than its shots") + add("shadow-count-short", edited(routed, both(at(S + ("omitted_shots",), 1), at(S + ("distance",), {"computed": False, "why": "a shot is omitted"}))), ["shadow"], "a shot said omitted beside counts that are all the shots: they sum to one more, and the distance, not computed, is no help") + add("shadow-distinct", edited(routed, at(S + ("distinct_outcomes",), 7)), ["shadow"], "a shadow that says more outcomes than it lists, none omitted") + + def by_mps(b): + route("method:mps", lambda r: None)(b) + b["result"]["planner"]["shadow"].update({"route": "method:mps", "class": "heuristic"}) + b["result"]["planner"]["shadow"]["request"]["method"] = "mps" + b["result"]["shadow"]["route"] = "method:mps" + b["result"]["shadow"]["request"]["method"] = "mps" + add("shadow-class-foreign", edited(routed, by_mps), ["shadow"], "a shadow run by mps stated bit-exact: it meets its plan, and mps has no such class") + add("shadow-bound-other", edited(routed, lambda b: b["result"]["shadow"]["distance"].update(sampling_tvd_bound=0.01)), ["shadow"], "a bound on the distance the shots alone leave that is not what the counts give") + + # --- what ran is the route chosen (the third check) + def paid_estimate(b): + b["result"]["cost"] = {"free": False, "estimate": {"free": False, "amount": "50", "currency": "USD", "unit": "job", "seconds": 0.0}, "charged": None, "confirmed": True} + add("cost-route-free-run-paid", edited(routed, paid_estimate), ["planner_choice"], "a run sealed at 50 USD on a route the reasoning calls free: not the route chosen") + + def sealed_free(b): + b["result"]["cost"] = {"free": True, "estimate": {"free": True, "seconds": 0.0}, "charged": None, "confirmed": False} + b["result"]["planner"]["kept"]["cost"]["charged"] = None + add("cost-route-paid-run-free", edited(named, sealed_free), ["planner_choice"], "a paid route chosen, its run sealed as free and unconfirmed") + add("cost-amount-other", edited(named, at(R + ("cost", "estimate", "amount"), "0.08")), ["planner_choice"], "a run sealed at another estimate than its route's") + + def unknown_sealed_free(b): + del b["request"]["contract"]["max_cost"] + del b["result"]["planner"]["kept"]["cost"] + route("provider:priced", lambda r: r["price"].update(money={"free": False, "unknown": "the provider gives no estimate"}))(b) + b["result"]["cost"] = {"free": True, "estimate": {"free": True, "seconds": 0.0}, "charged": None, "confirmed": False} + add("cost-unknown-run-free", edited(named, unknown_sealed_free), ["planner_choice"], "a route whose cost is not known, its run sealed as free and unconfirmed") + + def least_dropped(b): + del b["request"]["contract"]["max_cost"] + del b["result"]["planner"]["kept"]["cost"] + route("provider:priced", lambda r: r["price"]["money"].update(at_least=True))(b) + add("cost-at-least-dropped", edited(named, least_dropped), ["planner_choice"], "a route's estimate the least it can come to, its run's estimate sealed as the whole") + add("route-device-other", edited(routed, route("provider:ref", lambda r: r.update(device="reference:line-6"))), ["planner_choice"], "the route chosen names another device than the one that ran") + add("route-provenance-class", edited(routed, route("provider:priced", lambda r: r.update(provenance="silicon"))), ["planner_route"], "a provider's route whose class is not its provenance's") + + def shadow_width(b): + s = b["result"]["shadow"] + s["counts"] = dict(("0" + k, v) for k, v in s["counts"].items()) + a, c = b["result"]["counts"], s["counts"] + shots = sum(a.values()) + keys = sorted(set(a) | set(c)) + root = 0.0 + for k in keys: + root += math.sqrt(float(a.get(k, 0)) * float(c.get(k, 0))) + f = 0.0 + for k in keys: + f += coin_split(a.get(k, 0) + c.get(k, 0)) + s["distance"] = {"computed": True, "numerator": sum(abs(a.get(k, 0) - c.get(k, 0)) for k in keys), "denominator": 2 * shots, + "total_variation": sum(abs(a.get(k, 0) - c.get(k, 0)) for k in keys) / (2 * shots), + "hellinger_fidelity": root * root / (float(shots) * float(shots)), "sampling_tvd_bound": min(1.0, 0.5 * f / shots)} + add("shadow-width-other", edited(routed, shadow_width), ["shadow"], "a shadow whose outcomes are wider than the job's, its distance what they give") + add("route-mps-exact", edited(local, route("method:mps", lambda r: (r.update({"class": "exact", "outcome": "met"}), r.pop("rejected", None)))), ["planner_route", "planner_stable"], "the matrix product state's route stated exact, which a route of it never is") + + def registered(b): + rs = b["result"]["planner"]["routes"] + turbo = copy.deepcopy(next(r for r in rs if r["route"] == "method:exact")) + turbo.update({"route": "method:turbo", "method": "turbo"}) + rs.append(turbo) + add("route-registered-host-independent", edited(local, registered), ["planner_route", "planner_stable"], "a method the host registered, stated to depend on nothing of the host") + + def host_failed(b): + b["result"]["shadow"] = {"ran": False, "code": "failed", "why": "the host says it failed"} + add("shadow-said-failed", edited(routed, host_failed), [], "a shadow planned and said to have failed: valid to read, and run again by --recheck") return out @@ -713,10 +1016,21 @@ MADE = { "cli-compile.json": ("the command line: a compile, its certificate and its receipt", []), "cli-provider-reference.json": ("the command line, on the reference provider over a local process: a simulator's stated result", []), "cli-provider-reference-priced.json": ("the command line, on the reference provider with a price, confirmed with --yes", []), + "cli-contract-local.json": ("the command line under a contract: exact, a deadline and a ceiling, the cheapest route here chosen and its reasoning sealed", []), + "cli-contract-auto.json": ("the command line under a contract that names no class: auto's pick kept, held to a deadline", []), + "cli-contract-routed.json": ("the command line under a contract that allows the person's providers and wants a simulator's counts: the free one chosen, a classical method's counts and their distance beside its own", []), + "cli-contract-provider-priced.json": ("the command line on a provider it names, allowed by its contract and under a ceiling, confirmed with --yes: the estimate held to the ceiling, the charge to it after, and the shadow", []), + "cli-contract-routed-seed.json": ("the same routed job with the seed 2^53 - 2: its shadow's seed, the request's plus 2^32, wraps at 2^53", []), + "cli-contract-any.json": ("the command line under a contract that takes any class, the person's providers allowed: a free method here and a free provider tie on money and on time to the millisecond, and the method here comes first", []), + "cli-contract-bounded.json": ("the command line under a contract that wants bounded: a single-precision route does not meet it, and the state vector is chosen", []), + "cli-contract-fabric-cpu.json": ("the command line on the CPU it asks for, under a deadline: each route that runs on an accelerator rejected for it", []), + "cli-contract-target.json": ("the command line on a device target, the person's providers allowed beside it, under a deadline: the target's method is named, and the providers are not", []), + "cli-contract-pulse.json": ("the command line, a pulse program under a contract that wants bounded and a deadline: its one route", []), "service-run.json": ("the free job service, signed with its key", []), "service-run-stabilizer.json": ("the free job service: a stabilizer job with observables", []), "scripted-sampler-v2.json": ("sampler-v2 through a service that follows its contract", []), "scripted-prx-circuits.json": ("prx-circuits through a service that follows its contract", []), + "scripted-contract-prx-circuits.json": ("prx-circuits named under a contract that wants a device's counts, confirmed: its counts, the planner's reasoning, and a classical method's counts and their distance beside them", []), "scripted-native-turns.json": ("native-turns, its simulator, through a service that follows its contract", []), "scripted-native-turns-noise.json": ("native-turns, its simulator under a device's noise model", []), "scripted-cloud-tasks-processor.json": ("cloud-tasks on a processor: a verbatim box, rows of shots", []), diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-any.json b/wai/quantum-conformance/receipts/jobs/cli-contract-any.json new file mode 100644 index 000000000..73b484c66 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-any.json @@ -0,0 +1 @@ +{"status":"done","method":"stabilizer","why":"Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 6 of 15 routes that meet the contract","estimate":{"memory_bytes":67115270,"work":208},"request":{"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","shots":100,"seed":2,"contract":{"exactness":"any","deadline_seconds":60.0,"providers":"allowed"}},"result":{"method":"stabilizer","qubits":2,"gates":2,"accuracy":{"class":"exact"},"counts":{"00":54,"11":46},"distinct_outcomes":2,"omitted_shots":0,"outcome_dimension":1,"elapsed_ms":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"any","wanted_from":"contract","named":null,"question":"counts","auto":"method:stabilizer","host":{"job_bytes":17179869184,"providers":["ref","priced"]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":8e-9,"basis":"nominal"},"memory_bytes":268437922,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"statevector_single needs a GPU: this build has no GPU state vector"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":{"money":{"free":true},"time":{"seconds":2.496e-8,"basis":"nominal"},"memory_bytes":67115270,"work":208,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"pauli answers expectation values only"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.005603328,"basis":"nominal"},"memory_bytes":270532608,"work":3735552,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"stabilizer_rank answers amplitudes and expectation values"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"tensor_network answers amplitudes only"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":{"money":{"free":true},"time":{"seconds":1.35e-7,"basis":"nominal"},"memory_bytes":268435554,"work":900,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"cutrank_single needs a GPU: this build has no GPU cut-rank table"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"density_matrix is for noisy circuits (give \"noise\")"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"trajectories is for noisy circuits (give \"noise\")"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"pulse reads its own program, and runs only when a job names it"}},{"route":"provider:ref","kind":"provider","provider":"ref","class":"simulated","host_dependent":true,"price":{"money":{"free":true},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder"],"program":{"shots":100,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"met"},{"route":"provider:priced","kind":"provider","provider":"priced","class":"simulated","host_dependent":true,"price":{"money":{"free":false,"amount":"0.03","currency":"USD","unit":"shot"},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder","charged"],"program":{"shots":100,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"rejected","rejected":{"code":"cost_no_ceiling","why":"0.03 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider"}}],"choice":"method:stabilizer","why":"the cheapest of the 6 of 15 routes that meet the contract","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"e6de7586c9980adb8036dea7dc2777ba0acdb9a0138a3ef1da70c070133771f8","choice":false},"kept":{"deadline":{"seconds":60.0,"elapsed_ms":0,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"25467d1f1ec2e12f2c21f442c115289727fbda5e6d44bbc7d78c52c481599d24","signature":"c161c2af0b056e6fa763f56ace2cb21ef50e7d573e64200098dbb736a21c2564160701b82e79c79d4d1f15b6a2cb4a16dcbe87a90d53251efd9ac4930e955409"}}} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-auto.json b/wai/quantum-conformance/receipts/jobs/cli-contract-auto.json new file mode 100644 index 000000000..c3f28a7cb --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-auto.json @@ -0,0 +1 @@ +{"status":"done","method":"exact","why":"bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)","estimate":{"memory_bytes":134218112,"work":40},"request":{"qasm":"OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n","shots":500,"seed":3,"contract":{"deadline_seconds":600.0}},"result":{"method":"exact","qubits":3,"gates":5,"accuracy":{"class":"bit-exact"},"state_hash":"5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5","counts":{"000":254,"111":246},"distinct_outcomes":2,"omitted_shots":0,"elapsed_ms":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"bit-exact","wanted_from":"auto","named":null,"question":"counts","auto":"method:exact","host":{"job_bytes":17179869184,"providers":[]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":{"money":{"free":true},"time":{"seconds":2e-7,"basis":"nominal"},"memory_bytes":134218112,"work":40,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":268447588,"work":40,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants bit-exact"}},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants bit-exact"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants bit-exact"}},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants bit-exact"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.024723456,"basis":"nominal"},"memory_bytes":270794752,"work":16482304,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants bit-exact"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants bit-exact"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants bit-exact"}},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants bit-exact"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants bit-exact"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is estimate, and the job wants bit-exact"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants bit-exact"}}],"choice":"method:exact","why":"what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061","choice":true},"kept":{"deadline":{"seconds":600.0,"elapsed_ms":0,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"2c198a0bb868c91815a8573f898fe692b6eefba3d6d6b924cd420e02b2a19d6f","signature":"26e1443d1d91253c1064f457f81504c833d61f54d97a4a20edc878557a1e26348667298bfb6590453eaf2a44cc9311b038697fad274dd93f1adfadb660ba8a0f"}}} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-bounded.json b/wai/quantum-conformance/receipts/jobs/cli-contract-bounded.json new file mode 100644 index 000000000..881a8df15 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-bounded.json @@ -0,0 +1 @@ +{"status":"done","method":"statevector","why":"dense double-precision state vector of 2 qubits; the cheapest of the 1 of 13 routes that meet the contract","estimate":{"memory_bytes":268437922,"work":8},"request":{"qasm":"OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nrx(0.3) q[0];\ncx q[0], q[1];\nc = measure q;\n","shots":100,"seed":2,"contract":{"exactness":"bounded","deadline_seconds":60.0}},"result":{"method":"statevector","qubits":2,"gates":2,"accuracy":{"class":"exact","fusion":3},"counts":{"00":99,"11":1},"distinct_outcomes":2,"omitted_shots":0,"elapsed_ms":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"bounded","wanted_from":"contract","named":null,"question":"counts","auto":"method:statevector","host":{"job_bytes":17179869184,"providers":[]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"exact needs dyadic angles: the angle 0.3 is not a dyadic multiple of 2π (2πm/2^k, k ≤ 32) [Q500]"}},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":8e-9,"basis":"nominal"},"memory_bytes":268437922,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants bounded"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"stabilizer needs a Clifford circuit: Rx(0.3) is not a Clifford gate"}},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"pauli answers expectation values only"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.005603328,"basis":"nominal"},"memory_bytes":270532608,"work":3735552,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bounded"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"stabilizer_rank answers amplitudes and expectation values"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"tensor_network answers amplitudes only"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"Cx on qubits [0, 1] comes after a gate on qubit 0 that is not Clifford; cutrank takes a Clifford circuit, then one layer of one-qubit gates"}},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants bounded"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"density_matrix is for noisy circuits (give \"noise\")"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is estimate, and the job wants bounded"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"pulse reads its own program, and runs only when a job names it"}}],"choice":"method:statevector","why":"the cheapest of the 1 of 13 routes that meet the contract","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"7f32458b3eb3e371e44723491a3a020ebeb70d954a7d13936c61dcda9b1b19dc","choice":true},"kept":{"deadline":{"seconds":60.0,"elapsed_ms":0,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"a9ae845acd35e18289c0345762d2d2a0cf4c37a63e0b97305f86f6d8c70343c3","signature":"d8e40b438737df12bb78666c6353d966b201a9bc773d6343d160998c4653cd3280e9be72440f52f1e642345523aa9ec103cf8d1af6683d6431dc069a91933a02"}}} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-fabric-cpu.json b/wai/quantum-conformance/receipts/jobs/cli-contract-fabric-cpu.json new file mode 100644 index 000000000..c9c87d775 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-fabric-cpu.json @@ -0,0 +1 @@ +{"status":"done","method":"stabilizer","why":"Clifford circuit: the stabilizer tableau of 2 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (4 of 13 routes meet it)","estimate":{"memory_bytes":67115270,"work":208},"request":{"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","shots":100,"seed":2,"fabric":"cpu","contract":{"deadline_seconds":60.0}},"result":{"method":"stabilizer","qubits":2,"gates":2,"accuracy":{"class":"exact"},"counts":{"00":54,"11":46},"distinct_outcomes":2,"omitted_shots":0,"outcome_dimension":1,"elapsed_ms":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"exact","wanted_from":"auto","named":null,"question":"counts","auto":"method:stabilizer","host":{"job_bytes":17179869184,"providers":[]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":8e-9,"basis":"nominal"},"memory_bytes":268437922,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"fabric","why":"the job's placement on the fabric is not this route's"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":{"money":{"free":true},"time":{"seconds":2.496e-8,"basis":"nominal"},"memory_bytes":67115270,"work":208,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants exact"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.005603328,"basis":"nominal"},"memory_bytes":270532608,"work":3735552,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"stabilizer_rank answers amplitudes and expectation values"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"tensor_network answers amplitudes only"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":{"money":{"free":true},"time":{"seconds":1.35e-7,"basis":"nominal"},"memory_bytes":268435554,"work":900,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"fabric","why":"the job's placement on the fabric is not this route's"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"density_matrix is for noisy circuits (give \"noise\")"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is estimate, and the job wants exact"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants exact"}}],"choice":"method:stabilizer","why":"what auto picks, which meets the contract: the contract names no class, so it keeps auto's (4 of 13 routes meet it)","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"e6de7586c9980adb8036dea7dc2777ba0acdb9a0138a3ef1da70c070133771f8","choice":true},"kept":{"deadline":{"seconds":60.0,"elapsed_ms":0,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"369262e1f009fe7e34e4c5f81a3e46a751224bbfb4e84204952f85b046d198b8","signature":"384afecbc4152057acebc96f86b3374d81417d291f560011bbac0cbe5aa4361d33c09512c2713c48247cf7c92f4a53f6faa2376a134e138ae0c40b895f85130c"}}} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-local.json b/wai/quantum-conformance/receipts/jobs/cli-contract-local.json new file mode 100644 index 000000000..fa6ac9be5 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-local.json @@ -0,0 +1 @@ +{"status":"done","method":"stabilizer","why":"Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract","estimate":{"memory_bytes":67172870,"work":2008},"request":{"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","shots":1000,"seed":7,"contract":{"exactness":"exact","max_cost":{"amount":"1","currency":"USD"},"deadline_seconds":60.0}},"result":{"method":"stabilizer","qubits":2,"gates":2,"accuracy":{"class":"exact"},"counts":{"11":505,"00":495},"distinct_outcomes":2,"omitted_shots":0,"outcome_dimension":1,"elapsed_ms":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"exact","wanted_from":"contract","named":null,"question":"counts","auto":"method:stabilizer","host":{"job_bytes":17179869184,"providers":[]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":8e-9,"basis":"nominal"},"memory_bytes":268459522,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants exact"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":{"money":{"free":true},"time":{"seconds":2.4096e-7,"basis":"nominal"},"memory_bytes":67172870,"work":2008,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants exact"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.027721728,"basis":"nominal"},"memory_bytes":270532608,"work":18481152,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"stabilizer_rank answers amplitudes and expectation values"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"tensor_network answers amplitudes only"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":{"money":{"free":true},"time":{"seconds":1.35e-6,"basis":"nominal"},"memory_bytes":268435554,"work":9000,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"met"},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants exact"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"cannot","why":"density_matrix is for noisy circuits (give \"noise\")"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is estimate, and the job wants exact"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants exact"}}],"choice":"method:stabilizer","why":"the cheapest of the 4 of 13 routes that meet the contract","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e","choice":true},"kept":{"deadline":{"seconds":60.0,"elapsed_ms":0,"kept":true},"cost":{"max_cost":{"amount":"1","currency":"USD"},"charged":null,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"105fcdb97bff923e0420b8a5a7b5340eeab26a68b1f257fffc65b4e7a545af09","signature":"fe84735496fddb35013a8db356b40ff2ebba4fe7c5a7851208c5396ded3b9146a1ee0da323b4b8d8174891c862d52bb5aab55ad034bfce0795592a4dcfb6d205"}}} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-provider-priced.json b/wai/quantum-conformance/receipts/jobs/cli-contract-provider-priced.json new file mode 100644 index 000000000..eb0b2558a --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-provider-priced.json @@ -0,0 +1 @@ +{"status":"done","method":"provider","why":"on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent","request":{"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","shots":300,"seed":4,"contract":{"max_cost":{"amount":"1","currency":"USD"},"providers":"allowed"},"provider":"priced"},"result":{"method":"provider","qubits":2,"gates":2,"accuracy":{"class":"simulated","note":"counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would"},"shots":300,"provider":{"name":"priced","kind":"process","protocol":"wai.quantum.provider/1","device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","qubits":5,"basis":"rzsxxcz","describe":"c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439"},"calibration":"reference-f2d9fe570421","compiled":{"basis":"rzsxxcz","program":"b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9","hash":"BLAKE3 of the program's OpenQASM 3 text, qasm3","qasm3":"OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n","native_gates":9,"two_qubit_gates":1,"swaps":0,"layout":[0,1],"final_layout":[0,1],"checked":"the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent","placement":{"chosen":"the compiler's own layout, the fewest swaps: the description states no errors"}},"job":{"id":"ref-1","polls":1},"ideal":{"computed":true,"method":"exact","total_variation_distance":0.03666666666666665,"hellinger_fidelity":0.998653743148044,"sampling_tvd_expected":0.023032943298089033,"ideal_outcomes":2,"note":"the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent"},"cost":{"free":false,"estimate":{"free":false,"amount":"0.09","currency":"USD","unit":"shot","seconds":0.0},"charged":{"amount":"0.09","currency":"USD"},"confirmed":true},"energy":{"unmetered":"the work ran at the provider; this host's meter would read only the wait"},"counts_source":"shots","execution":{"stated_by":"provider","mitigation":"none","twirling":"none","decoupling":"none","remapping":"none","optimisation":"none","verbatim":true,"note":"the reference simulates the program's gates as written, on the qubits named, and corrects nothing"},"counts":{"11":161,"00":139},"distinct_outcomes":2,"omitted_shots":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"simulated","wanted_from":"named","named":"provider:priced","question":"counts","auto":null,"host":{"job_bytes":17179869184,"providers":["priced"]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"not_named","why":"the job names another route"}},{"route":"provider:priced","kind":"provider","provider":"priced","class":"simulated","host_dependent":true,"price":{"money":{"free":false,"amount":"0.09","currency":"USD","unit":"shot"},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder","charged"],"program":{"shots":300,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"chosen"}],"choice":"provider:priced","why":"the route the job names, which meets its contract (1 of 14 routes)","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f","choice":false},"shadow":{"route":"method:exact","class":"bit-exact","request":{"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","shots":300,"seed":4294967300,"method":"exact"},"budget_seconds":300.0,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]}},"kept":{"cost":{"max_cost":{"amount":"1","currency":"USD"},"charged":{"amount":"0.09","currency":"USD"},"kept":true}}},"shadow":{"ran":true,"route":"method:exact","accuracy":{"class":"bit-exact"},"request":{"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","shots":300,"seed":4294967300,"method":"exact"},"shots":300,"counts":{"00":161,"11":139},"distinct_outcomes":2,"omitted_shots":0,"distance":{"computed":true,"numerator":44,"denominator":600,"total_variation":0.07333333333333333,"hellinger_fidelity":0.9946222222222221,"sampling_tvd_bound":0.04602751441903442},"elapsed_ms":0},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"adb960d9232ebd72080b05dcbde26df4cbc594e26b9a3c717178087302139864","signature":"884e8d86ca7373ceed84a319c6593bac1241bfba9ca74b4fe107c44947808e48ffc21d04b48abbca58367338a6915f74d0be578baa6b4a465b90ddc59e35e90e"}},"id":"pj-e158396f1fd8f81d","submitted_ms":1794033072602,"finished_ms":1794033072605} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-pulse.json b/wai/quantum-conformance/receipts/jobs/cli-contract-pulse.json new file mode 100644 index 000000000..242aa74be --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-pulse.json @@ -0,0 +1 @@ +{"status":"done","method":"pulse","why":"a pulse schedule of 164 samples (82 ns) on $0 at 2 levels: 164 steps of 0.5 ns, each a series of order 12, the error within 3.512e-21 with rounding estimated at 2.840e-12; the cheapest of the 1 of 1 routes that meet the contract","estimate":{"memory_bytes":33566400,"work":55104},"request":{"qasm":"OPENQASM 3.0;\ndefcalgrammar \"openpulse\";\ncal {\n extern port d0;\n extern port a0;\n frame q0 = newframe(d0, 5.0e9, 0);\n frame c0 = newframe(a0, 5.0e9, 0);\n}\ndefcal x $0 { play(q0, drag(0.4, 64dt, 16dt, 0.2)); }\ndefcal measure $0 -> bit { return capture_v2(c0, 100dt); }\nbit c;\nx $0;\nc = measure $0;\n","shots":50,"seed":2,"method":"pulse","contract":{"exactness":"bounded","deadline_seconds":60.0}},"result":{"method":"pulse","qubits":1,"gates":2,"accuracy":{"class":"bounded","bound":2.8403945897125026e-12,"truncation_bound":3.511502073909511e-21,"rounding_estimate":2.8403945862010005e-12,"tolerance":1e-6,"norm":"trace","note":"every probability is within bound of the exact solution of the pulse model's master equation: the series' truncation proved, the rounding an estimate; the model itself (its levels, the rotating frame and the rotating-wave approximation, the envelope held for each sample) is what is solved"},"counts":{"1":46,"0":4},"distinct_outcomes":2,"omitted_shots":0,"shots":50,"diagnostics":[{"code":"Q453","outcome":"lowered","message":"a `cal` block read as OpenPulse and run here","line":3,"column":1,"length":5},{"code":"Q453","outcome":"lowered","message":"the `defcal` of x read as OpenPulse; it runs at each call","line":9,"column":1,"length":53},{"code":"Q453","outcome":"lowered","message":"the `defcal` of measure read as OpenPulse; it runs at each call","line":10,"column":1,"length":58}],"pulse":{"read":"the captures, at their one first sample, into the program's bits","outcome_bits":["c"],"distribution":{"0":0.12956041250210984,"1":0.8704395874978892},"populations":{"0":0.12956041250210984,"1":0.8704395874978892},"simulated_qubits":[0],"captures":[{"frame":"c0","qubit":0,"start":64,"start_ns":32.0,"bit":"c","p1":0.8704395874978892,"p2":0.0}],"trace":0.999999999999999,"density_hash":"09778fae666fc72fbac7b86d35f38c7a7e7fc16eb3c3799b0db32da0dc8767a4","duration":164,"duration_ns":82.0,"integrator":{"name":"taylor","order":12,"dt_ns":0.5,"substeps":1,"step_ns":0.5,"steps":164,"norm_max":0.2512047429452378,"frame":"each sample in the frame of each qubit's tone, the generator constant over it, then a diagonal phase back"},"device":{"levels":2,"dt_ns":0.5,"qubits":[{"qubit":0,"frequency_hz":5000000000.0,"rabi_hz":50000000.0,"anharmonicity_hz":-300000000.0,"from":{"frequency":"default","rabi":"default","anharmonicity":"default","t1":"none","t2":"none"}}],"couplings":[],"model":"each qubit a ladder of its levels in the frame rotating at its frequency, under the rotating-wave approximation, the envelope held for each sample; relaxation and pure dephasing from T1 and T2; static ZZ couplings"},"calibration":{"program":"f9b61296e932d2a5a5e9ab81f405f05bcf9900dacf27cbbeadf9ccaef001e0bb","calibrations":"48d81e250c5a875c58ba41229b4e2477f160e6e84f85a901dfff3fd7682b1a89","schedule":"9424e49a95d76eb70bf89923d05b5f7aca92678bd95520953373d415cc1b9267","device":"b18083ab12fd0d2f46d3d125c855119ca7f7dc0f2d73dace7d7fe5e557668b39"},"not_modelled":["the readout: a capture reads its qubit's state at its first sample, a level above 0 as 1"]},"verdict":{"schema":"wai.quantum.verdict/1","level":"executed","rank":2,"holds":null,"statement":"Executed on pulse (bounded); no intent was given, so nothing was checked against one.","parsed":{"ok":true,"diagnostics":[{"code":"Q453","outcome":"lowered","message":"a `cal` block read as OpenPulse and run here","line":3,"column":1,"length":5},{"code":"Q453","outcome":"lowered","message":"the `defcal` of x read as OpenPulse; it runs at each call","line":9,"column":1,"length":53},{"code":"Q453","outcome":"lowered","message":"the `defcal` of measure read as OpenPulse; it runs at each call","line":10,"column":1,"length":58}]},"executed":{"method":"pulse","accuracy":"bounded"},"intent":[],"critique":[],"repairs":[]},"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"bounded","wanted_from":"contract","named":"method:pulse","question":"counts","auto":null,"host":{"job_bytes":17179869184,"providers":[]},"routes":[{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":{"money":{"free":true},"time":{"seconds":0.000055104,"basis":"nominal"},"memory_bytes":33566400,"work":55104,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"}],"choice":"method:pulse","why":"the cheapest of the 1 of 1 routes that meet the contract","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:pulse"],"digest":"66699259c0f19f46979dc8a807893b52eaa894a2d6db6a3d7722004e484db32b","choice":true},"kept":{"deadline":{"seconds":60.0,"elapsed_ms":0,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"645a9ebd1f46804cf7c7e3eb4ea5f24bcceb875368f154a21a4bb1ea853ffd00","signature":"8c6b7778c8e3a1a7344f6c751e8c3f96dbbe24ba4363d3254af22980ec0769b23679cd7397c2a298c2221437550041a8d31534a9ea9320c203432575721a3203"}}} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-routed-seed.json b/wai/quantum-conformance/receipts/jobs/cli-contract-routed-seed.json new file mode 100644 index 000000000..64bd128d0 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-routed-seed.json @@ -0,0 +1 @@ +{"status":"done","method":"provider","why":"on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent","request":{"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","shots":300,"seed":9007199254740990,"contract":{"exactness":"simulated","providers":"allowed"}},"result":{"method":"provider","qubits":2,"gates":2,"accuracy":{"class":"simulated","note":"counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would"},"shots":300,"provider":{"name":"ref","kind":"process","protocol":"wai.quantum.provider/1","device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","qubits":5,"basis":"rzsxxcz","describe":"0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0"},"calibration":"reference-f2d9fe570421","compiled":{"basis":"rzsxxcz","program":"b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9","hash":"BLAKE3 of the program's OpenQASM 3 text, qasm3","qasm3":"OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n","native_gates":9,"two_qubit_gates":1,"swaps":0,"layout":[0,1],"final_layout":[0,1],"checked":"the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent","placement":{"chosen":"the compiler's own layout, the fewest swaps: the description states no errors"}},"job":{"id":"ref-1","polls":1},"ideal":{"computed":true,"method":"exact","total_variation_distance":0.013333333333333308,"hellinger_fidelity":0.9998221906060416,"sampling_tvd_expected":0.023032943298089033,"ideal_outcomes":2,"note":"the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent"},"cost":{"free":true,"estimate":{"free":true,"seconds":0.0},"charged":null,"confirmed":false},"energy":{"unmetered":"the work ran at the provider; this host's meter would read only the wait"},"counts_source":"shots","execution":{"stated_by":"provider","mitigation":"none","twirling":"none","decoupling":"none","remapping":"none","optimisation":"none","verbatim":true,"note":"the reference simulates the program's gates as written, on the qubits named, and corrects nothing"},"counts":{"11":154,"00":146},"distinct_outcomes":2,"omitted_shots":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"simulated","wanted_from":"contract","named":null,"question":"counts","auto":"method:stabilizer","host":{"job_bytes":17179869184,"providers":["ref","priced"]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is bit-exact, and the job wants simulated"}},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":8e-9,"basis":"nominal"},"memory_bytes":268442722,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants simulated"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":{"money":{"free":true},"time":{"seconds":7.296e-8,"basis":"nominal"},"memory_bytes":67128070,"work":608,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants simulated"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.010518528000000001,"basis":"nominal"},"memory_bytes":270532608,"work":7012352,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is heuristic, and the job wants simulated"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":{"money":{"free":true},"time":{"seconds":4.05e-7,"basis":"nominal"},"memory_bytes":268435554,"work":2700,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants simulated"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is estimate, and the job wants simulated"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants simulated"}},{"route":"provider:ref","kind":"provider","provider":"ref","class":"simulated","host_dependent":true,"price":{"money":{"free":true},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder"],"program":{"shots":300,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"chosen"},{"route":"provider:priced","kind":"provider","provider":"priced","class":"simulated","host_dependent":true,"price":{"money":{"free":false,"amount":"0.09","currency":"USD","unit":"shot"},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder","charged"],"program":{"shots":300,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"rejected","rejected":{"code":"cost_no_ceiling","why":"0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider"}}],"choice":"provider:ref","why":"the cheapest of the 1 of 15 routes that meet the contract","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a","choice":false},"shadow":{"route":"method:exact","class":"bit-exact","request":{"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","shots":300,"seed":4294967294,"method":"exact"},"budget_seconds":300.0,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]}},"kept":{}},"shadow":{"ran":true,"route":"method:exact","accuracy":{"class":"bit-exact"},"request":{"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","shots":300,"seed":4294967294,"method":"exact"},"shots":300,"counts":{"00":151,"11":149},"distinct_outcomes":2,"omitted_shots":0,"distance":{"computed":true,"numerator":10,"denominator":600,"total_variation":0.016666666666666666,"hellinger_fidelity":0.9997221944339458,"sampling_tvd_bound":0.046103716364460375},"elapsed_ms":0},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"f6073ce2965dc9ad90ddd3fcb6cbcbdfc722ebaa30cdf540517ed93b5b394d39","signature":"fd220074ac10f205ffc4d2f99571cccd5e6a839a6409ad746b592f4c3500ee448969df9bc0b7bebf1e3bf43d87511ca8b3d2b61f5060317c31bf6baaf6c1dc0b"}},"id":"pj-255b9772ebc3d0cf","submitted_ms":1794033072543,"finished_ms":1794033072546} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-routed.json b/wai/quantum-conformance/receipts/jobs/cli-contract-routed.json new file mode 100644 index 000000000..c0012f747 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-routed.json @@ -0,0 +1 @@ +{"status":"done","method":"provider","why":"on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent","request":{"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","shots":300,"seed":4,"contract":{"exactness":"simulated","providers":"allowed"}},"result":{"method":"provider","qubits":2,"gates":2,"accuracy":{"class":"simulated","note":"counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would"},"shots":300,"provider":{"name":"ref","kind":"process","protocol":"wai.quantum.provider/1","device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","qubits":5,"basis":"rzsxxcz","describe":"0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0"},"calibration":"reference-f2d9fe570421","compiled":{"basis":"rzsxxcz","program":"b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9","hash":"BLAKE3 of the program's OpenQASM 3 text, qasm3","qasm3":"OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n","native_gates":9,"two_qubit_gates":1,"swaps":0,"layout":[0,1],"final_layout":[0,1],"checked":"the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent","placement":{"chosen":"the compiler's own layout, the fewest swaps: the description states no errors"}},"job":{"id":"ref-1","polls":1},"ideal":{"computed":true,"method":"exact","total_variation_distance":0.03666666666666665,"hellinger_fidelity":0.998653743148044,"sampling_tvd_expected":0.023032943298089033,"ideal_outcomes":2,"note":"the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent"},"cost":{"free":true,"estimate":{"free":true,"seconds":0.0},"charged":null,"confirmed":false},"energy":{"unmetered":"the work ran at the provider; this host's meter would read only the wait"},"counts_source":"shots","execution":{"stated_by":"provider","mitigation":"none","twirling":"none","decoupling":"none","remapping":"none","optimisation":"none","verbatim":true,"note":"the reference simulates the program's gates as written, on the qubits named, and corrects nothing"},"counts":{"11":161,"00":139},"distinct_outcomes":2,"omitted_shots":0,"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"simulated","wanted_from":"contract","named":null,"question":"counts","auto":"method:stabilizer","host":{"job_bytes":17179869184,"providers":["ref","priced"]},"routes":[{"route":"method:exact","kind":"local","method":"exact","class":"bit-exact","host_dependent":false,"auto_rank":20,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is bit-exact, and the job wants simulated"}},{"route":"method:statevector","kind":"local","method":"statevector","class":"exact","host_dependent":false,"auto_rank":30,"price":{"money":{"free":true},"time":{"seconds":8e-9,"basis":"nominal"},"memory_bytes":268442722,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:statevector_single","kind":"local","method":"statevector_single","class":"single","host_dependent":true,"auto_rank":40,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants simulated"}},{"route":"method:stabilizer","kind":"local","method":"stabilizer","class":"exact","host_dependent":false,"auto_rank":10,"price":{"money":{"free":true},"time":{"seconds":7.296e-8,"basis":"nominal"},"memory_bytes":67128070,"work":608,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:pauli","kind":"local","method":"pauli","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants simulated"}},{"route":"method:mps","kind":"local","method":"mps","class":"heuristic","host_dependent":false,"auto_rank":60,"price":{"money":{"free":true},"time":{"seconds":0.010518528000000001,"basis":"nominal"},"memory_bytes":270532608,"work":7012352,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is heuristic, and the job wants simulated"}},{"route":"method:stabilizer_rank","kind":"local","method":"stabilizer_rank","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:tensor_network","kind":"local","method":"tensor_network","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:cutrank","kind":"local","method":"cutrank","class":"exact","host_dependent":false,"auto_rank":50,"price":{"money":{"free":true},"time":{"seconds":4.05e-7,"basis":"nominal"},"memory_bytes":268435554,"work":2700,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:cutrank_single","kind":"local","method":"cutrank_single","class":"single","host_dependent":true,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is single, and the job wants simulated"}},{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is exact, and the job wants simulated"}},{"route":"method:trajectories","kind":"local","method":"trajectories","class":"estimate","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is estimate, and the job wants simulated"}},{"route":"method:pulse","kind":"local","method":"pulse","class":"bounded","host_dependent":false,"auto_rank":null,"price":null,"outcome":"rejected","rejected":{"code":"class","why":"its class is bounded, and the job wants simulated"}},{"route":"provider:ref","kind":"provider","provider":"ref","class":"simulated","host_dependent":true,"price":{"money":{"free":true},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder"],"program":{"shots":300,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"chosen"},{"route":"provider:priced","kind":"provider","provider":"priced","class":"simulated","host_dependent":true,"price":{"money":{"free":false,"amount":"0.09","currency":"USD","unit":"shot"},"time":{"seconds":0.0,"basis":"provider"},"memory_bytes":null,"work":null,"energy":{"joules":null,"why":"no provider states a job's energy before it runs"},"leaves_out":["energy","mitigation","decoder","charged"],"program":{"shots":300,"native_gates":9,"two_qubit_gates":1,"swaps":0}},"device":"reference:line-5","provenance":"simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given","outcome":"rejected","rejected":{"code":"cost_no_ceiling","why":"0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider"}}],"choice":"provider:ref","why":"the cheapest of the 1 of 15 routes that meet the contract","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:exact","method:statevector","method:stabilizer","method:pauli","method:mps","method:stabilizer_rank","method:tensor_network","method:cutrank","method:density_matrix","method:trajectories","method:pulse"],"digest":"e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a","choice":false},"shadow":{"route":"method:exact","class":"bit-exact","request":{"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","shots":300,"seed":4294967300,"method":"exact"},"budget_seconds":300.0,"price":{"money":{"free":true},"time":{"seconds":4e-8,"basis":"nominal"},"memory_bytes":134217920,"work":8,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]}},"kept":{}},"shadow":{"ran":true,"route":"method:exact","accuracy":{"class":"bit-exact"},"request":{"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","shots":300,"seed":4294967300,"method":"exact"},"shots":300,"counts":{"00":161,"11":139},"distinct_outcomes":2,"omitted_shots":0,"distance":{"computed":true,"numerator":44,"denominator":600,"total_variation":0.07333333333333333,"hellinger_fidelity":0.9946222222222221,"sampling_tvd_bound":0.04602751441903442},"elapsed_ms":0},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"71770ed37d2687b9f97392667c58c80a80836d6852619f0498aa1dcfec9e4996","signature":"ffe2160d7de0f0939ebb0146de12a9617976cff8049ab415f5ce85b3964cf66cdc3a3f216926f69820f2b6d9d4ebe0b206442d1e6aac5931bf27d2808671e508"}},"id":"pj-6059aefb7ace70bc","submitted_ms":1794033072508,"finished_ms":1794033072511} diff --git a/wai/quantum-conformance/receipts/jobs/cli-contract-target.json b/wai/quantum-conformance/receipts/jobs/cli-contract-target.json new file mode 100644 index 000000000..2256afece --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/cli-contract-target.json @@ -0,0 +1 @@ +{"status":"done","method":"density_matrix","why":"density matrix of the 2 physical qubits the program touches, each gate and channel one superoperator pass, under the noise of the target synthetic-line-5 (calibration content:0b152c6f06102941): the program compiled to rzsxxcz on physical qubits [3, 4], 0 swaps, expected success 0.9563; each gate costed as the target's own, equal up to one-qubit gates; the route the job names, which meets its contract (1 of 1 routes)","estimate":{"memory_bytes":268435720,"work":400},"request":{"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","shots":50,"seed":2,"contract":{"deadline_seconds":60.0,"providers":"allowed"},"target":"synthetic-line-5"},"result":{"method":"density_matrix","qubits":2,"gates":2,"accuracy":{"class":"exact","note":"the noisy state under the target's noise model, exactly: a model of the device from its calibration snapshot: each gate's reported error as depolarising noise beside the amplitude damping and dephasing its T1, T2 and duration give, idling relaxed the same way, and each qubit's readout by its assignment errors; Markovian and gate-local, so crosstalk, leakage, coherent over-rotation and drift are not modelled; counts are seeded samples of its distribution, each bit misread by its qubit's assignment errors; expectation values are of the state before the measurement, with no readout error"},"counts":{"00":26,"11":22,"01":2},"distinct_outcomes":3,"omitted_shots":0,"ideal":{"computed":true,"total_variation_distance":0.03964591211886446,"hellinger_fidelity":0.960218501561203,"note":"the noisy distribution over the classical bits, exactly, against the circuit's ideal one by the bit-exact state vector: how far the target's noise moves the answer"},"target":{"name":"synthetic-line-5","hash":"a618b0e1c671834a0a8967524b4a7018752f50e3c11d98c1c49a687806e81701","hash_is":"BLAKE3 of the target document's RFC 8785 text","calibration":{"id":"content:0b152c6f06102941","timestamp":"2026-10-01T09:00:00+00:00"},"source":{"format":"device-properties","note":"synthetic: written for wai-quantum in the shape of the device-properties format, its numbers made up; no device's data"},"placement":{"basis":"rzsxxcz","exact":false,"layout":[3,4],"final_layout":[3,4],"swaps":0,"native_gates":9,"two_qubit_gates":1,"expected_success":0.9563103156162862,"fewest_swaps":{"layout":[0,1],"swaps":0,"expected_success":0.9491455074213893},"layouts_compared":8,"chosen":"noise-aware: of 8 layouts and their routes, the highest expected success (0.956310, against 0.949146 for the fewest swaps)","expected_success_is":"the product of each gate's success (one less its reported error, or where none is reported its relaxation over its duration) and each measured qubit's readout success (one less the mean of its assignment errors); idling is in the noise model, not in this figure","checked":"the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator","notes":["the target's gates do not hold one of the compiler's sets, so the program is compiled to rz sx x cz and each gate costed as the target's (cz as cx): the same up to one-qubit gates, which are not counted; a simulation of the device, not a program it runs as it is"]},"noise":{"model":"a model of the device from its calibration snapshot: each gate's reported error as depolarising noise beside the amplitude damping and dephasing its T1, T2 and duration give, idling relaxed the same way, and each qubit's readout by its assignment errors; Markovian and gate-local, so crosstalk, leakage, coherent over-rotation and drift are not modelled","simulated_qubits":[3,4],"duration_ns":491.0,"idle_ns":35.5,"channels":16,"one_qubit_depolarizing":{"gates":8,"mean":0.000025084801525975534},"two_qubit_depolarizing":{"gates":1,"mean":0.0029999418028110424},"readout":[{"logical":0,"physical":3,"p01":0.006877,"p10":0.03886},{"logical":1,"physical":4,"p01":0.007857,"p10":0.01804}],"notes":[]}},"engine":{"name":"wai-quantum","version":"0.8.1"},"schema":"wai.quantum.job-result/1","planner":{"format":"wai.quantum.planner/1","wanted":"exact","wanted_from":"named","named":"method:density_matrix","question":"counts","auto":null,"host":{"job_bytes":17179869184,"providers":[]},"routes":[{"route":"method:density_matrix","kind":"local","method":"density_matrix","class":"exact","host_dependent":false,"auto_rank":null,"price":{"money":{"free":true},"time":{"seconds":7.2e-8,"basis":"nominal"},"memory_bytes":268435720,"work":400,"energy":{"joules":null,"why":"this host estimates no job's energy before it runs"},"leaves_out":[]},"outcome":"chosen"}],"choice":"method:density_matrix","why":"the route the job names, which meets its contract (1 of 1 routes)","stable":{"scope":"digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host","routes":["method:density_matrix"],"digest":"16b4bfb6541720b9990c891168f637b933f09ef1134cd0bfb5165ac5d248a7e3","choice":false},"kept":{"deadline":{"seconds":60.0,"elapsed_ms":1,"kept":true}}},"energy":{"unmetered":"the command line does not meter a run's energy"},"receipt":{"alg":"ed25519","canon":"rfc8785","key":"197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61","digest":"756e787363f6c18d3392c97f574846e8d5ec9642cb5eade81f698068fa650d9a","signature":"03bfebaee776044398a164427e01924ded2bce9c4ae4bf5dbad6e408b02e49564e7017f6beaf5b5b42e8655825b2306942fc448b4ea0b8e902b0580848761405"}}} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-approximate-rejected.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-approximate-rejected.json new file mode 100644 index 000000000..529aadf79 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-approximate-rejected.json @@ -0,0 +1,545 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + }, + "approximate": true + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8505d448ae9f3064944a6894d84264bc5dd76090009c74f880eb5cba7f80710f", + "signature": "741787b0d0037eb20eb5d2de281be60608910d2cc4eb00900e9c0d82409a2f8f6e55813115d9c9d4259054c1dfceb00f82f3dbe74f24d1fc1573ef6ab687b306" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-at-least-claimed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-at-least-claimed.json new file mode 100644 index 000000000..3186c745f --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-at-least-claimed.json @@ -0,0 +1,451 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "at_least": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "4b2da8950e2e4033a403221c00b50ef935350c51e7f78b3857ec0bf85e4ed274", + "signature": "66c587831dc4ceabf0b3bf30dcba86c89412f88bd0b649d79e9c3eb4037272d01139b82b99c307d39412e7f1868e1df520791e4312d442e7ceda639ba5ce850b" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-at-least-false.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-at-least-false.json new file mode 100644 index 000000000..7c13456c7 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-at-least-false.json @@ -0,0 +1,545 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "at_least": false + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d18a44908d1e326f1f973e38e8baa79677d8b43a6e6503a41165ef373b8c9dc0", + "signature": "a865c48455b9443faec53460fa8e38f4bebae7b2d868fbf71c37beba7fc90a75ab31a24c4330d8c52e775c960595ce666c07e14d368db1b6ee326cf4fbc9a60d" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-other.json new file mode 100644 index 000000000..d5f0cad22 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-other.json @@ -0,0 +1,312 @@ +{ + "status": "done", + "method": "exact", + "why": "bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "estimate": { + "memory_bytes": 134218112, + "work": 40 + }, + "request": { + "qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n", + "shots": 500, + "seed": 3, + "contract": { + "deadline_seconds": 600.0 + } + }, + "result": { + "method": "exact", + "qubits": 3, + "gates": 5, + "accuracy": { + "class": "bit-exact" + }, + "state_hash": "5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5", + "counts": { + "000": 254, + "111": 246 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "bit-exact", + "wanted_from": "auto", + "named": null, + "question": "counts", + "auto": "method:statevector", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2e-07, + "basis": "nominal" + }, + "memory_bytes": 134218112, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 268447588, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.024723456, + "basis": "nominal" + }, + "memory_bytes": 270794752, + "work": 16482304, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants bit-exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + } + ], + "choice": "method:exact", + "why": "what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 600.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "6397742e38ce279d22b434b5432eb585a7e6310776b7cb57bda375d95b96b002", + "signature": "926aaea5c187a5ce7755db94cc1b172bb24bff000bd8e3c32b79e58b32dcebb3866d9dcd6e31296d545de25e7e7689da9189fade243bc8d311eb6c35da969208" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-lowered.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-lowered.json new file mode 100644 index 000000000..13974762e --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-lowered.json @@ -0,0 +1,312 @@ +{ + "status": "done", + "method": "exact", + "why": "bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "estimate": { + "memory_bytes": 134218112, + "work": 40 + }, + "request": { + "qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n", + "shots": 500, + "seed": 3, + "contract": { + "deadline_seconds": 600.0 + } + }, + "result": { + "method": "exact", + "qubits": 3, + "gates": 5, + "accuracy": { + "class": "bit-exact" + }, + "state_hash": "5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5", + "counts": { + "000": 254, + "111": 246 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "bit-exact", + "wanted_from": "auto", + "named": null, + "question": "counts", + "auto": "method:exact", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2e-07, + "basis": "nominal" + }, + "memory_bytes": 134218112, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 5, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 268447588, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.024723456, + "basis": "nominal" + }, + "memory_bytes": 270794752, + "work": 16482304, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants bit-exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + } + ], + "choice": "method:exact", + "why": "what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 600.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "920a77770f5fe060634a9dbc9dd638ec61f97811f4776a6f07a0053df4d7cb1e", + "signature": "945f272d15e56164423bf4db1adc893c5db1ecca130488de74473ff59030dd150f3743a49f37612e4b309f35afd4e6296a55c58ad572771d07cb42184e4a630d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-missing.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-missing.json new file mode 100644 index 000000000..c553d6297 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-missing.json @@ -0,0 +1,311 @@ +{ + "status": "done", + "method": "exact", + "why": "bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "estimate": { + "memory_bytes": 134218112, + "work": 40 + }, + "request": { + "qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n", + "shots": 500, + "seed": 3, + "contract": { + "deadline_seconds": 600.0 + } + }, + "result": { + "method": "exact", + "qubits": 3, + "gates": 5, + "accuracy": { + "class": "bit-exact" + }, + "state_hash": "5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5", + "counts": { + "000": 254, + "111": 246 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "bit-exact", + "wanted_from": "auto", + "named": null, + "question": "counts", + "auto": "method:exact", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2e-07, + "basis": "nominal" + }, + "memory_bytes": 134218112, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 268447588, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.024723456, + "basis": "nominal" + }, + "memory_bytes": 270794752, + "work": 16482304, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants bit-exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + } + ], + "choice": "method:exact", + "why": "what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 600.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "229928210ea46a8a118063b4ab59498bc46340f57b3382074a78e314b0de6001", + "signature": "774dffc7336ec083fe922d076d91980f2d8bb9427edc69a15d47a2d3fd187b390c5cacebe5620180964235e1347d9d8cb488cf4466d848682182da4db7a5380c" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-other.json new file mode 100644 index 000000000..630eff4b0 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-auto-rank-other.json @@ -0,0 +1,312 @@ +{ + "status": "done", + "method": "exact", + "why": "bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "estimate": { + "memory_bytes": 134218112, + "work": 40 + }, + "request": { + "qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n", + "shots": 500, + "seed": 3, + "contract": { + "deadline_seconds": 600.0 + } + }, + "result": { + "method": "exact", + "qubits": 3, + "gates": 5, + "accuracy": { + "class": "bit-exact" + }, + "state_hash": "5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5", + "counts": { + "000": 254, + "111": 246 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "bit-exact", + "wanted_from": "auto", + "named": null, + "question": "counts", + "auto": "method:exact", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2e-07, + "basis": "nominal" + }, + "memory_bytes": 134218112, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 268447588, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 65, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.024723456, + "basis": "nominal" + }, + "memory_bytes": 270794752, + "work": 16482304, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants bit-exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + } + ], + "choice": "method:exact", + "why": "what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 600.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "0d8795d6189083abac8ed6ee4a2288b72d38beb8a92d46ef2d8234320d809d03", + "signature": "e2dee694e3ffb76b40e4ca03a36e14398d8ce3cb92ad7bf7ea2e561fb483822addeb058b9769122ccfc1e52934feece756a25a6d9230d0c1438e45e775560a0d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-charged-over-stated.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-charged-over-stated.json new file mode 100644 index 000000000..199616ac8 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-charged-over-stated.json @@ -0,0 +1,450 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "1.5", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "1.5", + "currency": "USD" + }, + "kept": false + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "49804035ae6d80eef4306d45aa936976c2dfc4f466d75ed7ac01d4b3048e22c0", + "signature": "d65f8d157543b5f5fc506f96b9aea9cc1134e43d4248d8e2091a8df92c2227c6a30e85ff73dc9a2e08b97a90aa03cebc94dfb60c5ed568813bff22ddacc33700" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-charged-over.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-charged-over.json new file mode 100644 index 000000000..e9690bad2 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-charged-over.json @@ -0,0 +1,450 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "1.5", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "1.5", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "330b81d67073190de3693ade958c3facf8d27315ed3a94045113681aca7166f2", + "signature": "8df3472930b69fe0b157fbff36c648aa3c70a6324b5e3295ab2a1af2c563367cf2924b8d6eee354cf1e8409f1ba269c974af1bb6ae9042f3b346569706085402" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-choice-dearer.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-choice-dearer.json new file mode 100644 index 000000000..db415209b --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-choice-dearer.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "statevector", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:statevector", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "22250aa4a3fa19026453970598ef47b2bf3ee334fd99848ef957c9b1917c0c91", + "signature": "24ac10d8c8c91ca434e4d7ae501fd018001b0f1985d324486fc7933225cba7fb2e132e7f4d73a249013d0b13df23f6e8164d8e2f9f32dc86ac5468053391600b" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-choice-not-run.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-choice-not-run.json new file mode 100644 index 000000000..4e6c451c6 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-choice-not-run.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "statevector", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "a77dd911b3f4d938d21281f25b3c24bb86bef0942279ebcc13586a55c2fcd088", + "signature": "a56fd2981a590fe573ae93dbf8fa8397ad483ca7c936c62beb3075fd59e433b5d5b8b7bfe97526199d996932c2fd0f00c619ba09d7dabd66ac6a06441c411802" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-class-short.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-class-short.json new file mode 100644 index 000000000..a787a3eda --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-class-short.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "estimate" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "5f665f5cbac0f48cdc52e5173ca41d5e31ef846e945e6bccac21ed1567815a1e", + "signature": "ea5ad3d895c5835539c6e25fb7ee12915f093c99d1f2dc4c0ea73fc163ba42a09bb9e8e58003405f95f2eaa75c5ee6a7395b3e70a2e39ab40d74ad8507eeea0d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-amount-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-amount-other.json new file mode 100644 index 000000000..dce5ef63c --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-amount-other.json @@ -0,0 +1,450 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.08", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "4a58d60b22d06875dc98bc95e3bca81ad6dc33e8d7b39114bf034db35bf1f4e0", + "signature": "a0e9c85f3347b634ce77bb2f9a2ebc9e565e8c930632e1becb315cfb40ca8833665ab23fcce9782e39e2b6df0ea3235ecf31271864c2f91babc06370c2466606" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-at-least-dropped.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-at-least-dropped.json new file mode 100644 index 000000000..4d1b9cc89 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-at-least-dropped.json @@ -0,0 +1,435 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "at_least": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "0b97651e8a11914eaa5f5d8c0b69305b8979474670f9b9f61a5f864f42efadd3", + "signature": "aef4cf8266c9a82feeacb5686d1b753b499a58cd298d5f4b6494422c18abc0266ecbcf4e484c2bec4529b244d09525bda3159815b5ed64f34971ef639b8ee801" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-route-free-run-paid.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-route-free-run-paid.json new file mode 100644 index 000000000..9f8599e56 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-route-free-run-paid.json @@ -0,0 +1,547 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "50", + "currency": "USD", + "unit": "job", + "seconds": 0.0 + }, + "charged": null, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "21b63e110f5db9eb78f8bbe8bc3e0cc5c27026294f99bf750ac02d45c7d2808e", + "signature": "e9f33fed626b427bc208a79724d44468bd425f86f7ac9f421a530cd0a02a08a4c533cd176a16b9be3ea5fac09a93a8d784a5d097b537a584d92d2e1180a51506" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-route-paid-run-free.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-route-paid-run-free.json new file mode 100644 index 000000000..6c25821c4 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-route-paid-run-free.json @@ -0,0 +1,441 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d954f8069ecd70a9cd634ffb35f78b8319bffeb84c62b1272e44b31cb019b4f3", + "signature": "849f782a2f4e28992635ff8c8104b8930efbaf105152d93d38f9cfda3ecbded6f45e29aa0ab495a182dd75d513316a5bf38510fd2c110d94130966598772e305" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-unknown-run-free.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-unknown-run-free.json new file mode 100644 index 000000000..a5f8c216f --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-cost-unknown-run-free.json @@ -0,0 +1,426 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "unknown": "the provider gives no estimate" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "dd3fb51c8a678abaddd96d5eaf2f2867ca13733416b9c4ff113b0de7b3e75014", + "signature": "cbd07c049bbd7edeeacfc935b7f679f406ac81eb2fa1b38d4c12c9a433a227b05bacfd2a961b141371e24aed8abc4a132e7811b6c4ddd17d790c0ecc3db5ff0e" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-currency-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-currency-other.json new file mode 100644 index 000000000..5cc8d5141 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-currency-other.json @@ -0,0 +1,450 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "EUR" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "6addfa40b6f4b7c0a2e9138143e62fcfc82e8c1dbc696e279b615c1978936c63", + "signature": "3d7c4c8bf556f0a0cd5449e2f8c440931f98cb6dec1b65932349ff78985e6af65c6992fa971f331ed9550fb4d5cb6cb114c29a9d0ddf203839b37bd05484f206" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-deadline-unknown.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-deadline-unknown.json new file mode 100644 index 000000000..9f748ddf6 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-deadline-unknown.json @@ -0,0 +1,347 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": null, + "why": "said unknown" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "deadline_unknown", + "why": "its time is not known, and the contract gives a deadline" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "057ee039fa3589735a188c5be6890afe3007138cbb96a8222d212ba75907a45b", + "signature": "91ac7e6c6a5fa3d70d22e798efd6c816f017039b2493f23b94a8f91cbd0dbfd6bda4013f03c3b872bb55c73121e3da6293fccb780a01629aa479c573f8a51206" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-at-ceiling.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-at-ceiling.json new file mode 100644 index 000000000..436db5f19 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-at-ceiling.json @@ -0,0 +1,354 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "09f69a3d3bbdbbe0464a578877c1f96e49d5a56854d30d741b7a01a1076df1d3", + "signature": "754c3b79a37d4ddbd9194ed6417562b0b434a6e8974c04a0efac12a3fc9485df97bdd9922ab309e2045a153514b93fb875ecadd63de4a19846fe331021b6590b" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-estimate-at-ceiling.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-estimate-at-ceiling.json new file mode 100644 index 000000000..3f6c4c4d9 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-estimate-at-ceiling.json @@ -0,0 +1,354 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 2, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "fdffe2430bb7caf05f78894e831e7de1d472f4ce0704a54c2b86c2adcd411f86", + "signature": "520ac3748766d1cc5eda266885bdb88cb0dc33e3612561845b0112cd14f52a7510d0ceb7f6a97dcfb7d311bb6d9fef7628512b2eb542910bd22cafc671d16605" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-over-estimate.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-over-estimate.json new file mode 100644 index 000000000..4c9f41ef1 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-over-estimate.json @@ -0,0 +1,358 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 3, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "energy", + "why": "said so" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "c9f039a854f3c3c91eae40ef6bc88f47463866e5e9ac6ac28e9354113c1bd335", + "signature": "ac19a4e7f6541b7a4c0f4c6bdfabf754d979b4ab7235e73e02d5439c8939fe74bcfef41a7c13ab4dba379fe75d2fac354f7eb25ef6f3aa97196cf683445b6709" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-stable-claimed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-stable-claimed.json new file mode 100644 index 000000000..721c064f5 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-stable-claimed.json @@ -0,0 +1,354 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "54cca7fa5802c5a93c4ed2c0b5f32f6fd84768d897d6f06c36b97988aaf804c3", + "signature": "b5b9131d1c2a700cf83e79d8b1c726cc07e610a9c76ec5ee0a38e313f85623ecc096d01eb69161e14d0e330d97768dd986b19ed81acf6b4090c26b11e33a8602" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-unwatched-claimed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-unwatched-claimed.json new file mode 100644 index 000000000..8fde72056 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-unwatched-claimed.json @@ -0,0 +1,354 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 0.5, + "basis": "an estimate", + "unwatched": "nothing reads it" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "0be8cca715ecad7c6d564d6e98a4c8d3bcd877ba029eda3b78cbf1cb043a782a", + "signature": "49cec4379b6c8f731bdce79d33a53ddbfb68dccc62c92c6f49bf98770e2cacba8ae70b1191d2a2b7ee0fbc1e99d7b0bb95c3480c74ec34f320a8ca6013e89504" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-unwatched.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-unwatched.json new file mode 100644 index 000000000..fdd3b72b6 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-unwatched.json @@ -0,0 +1,358 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 0.5, + "basis": "an estimate", + "unwatched": "nothing reads it" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "energy_unwatched", + "why": "said so" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "6725b35c91fd9faf122594a12ba046b9c9917d8bc93a9671cbafc8ab867a32c5", + "signature": "685deec67e951f70261ba5e7d14151451c0959274759d598796bed882aeb18d429db39131293bde96b65b46f35588f009fe169571f44986927a65a8cb52b6409" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-watch-both.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-watch-both.json new file mode 100644 index 000000000..d855dfbdb --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-watch-both.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading", + "unwatched": "and yet" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "37de8da293cf8144268fc6c7bef7c99a90d3b208e350a610c392104aac10af23", + "signature": "5b9a211c5c1015e1c396bba699648e6c0e785a6bc4294c1f66d3f0ebe5692e2a3d05c53397b94c2c35d7fe8a1cf93fc2a338733af8ae0bcfd038a105af7c1b08" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-watch-form.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-watch-form.json new file mode 100644 index 000000000..503957fcd --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-energy-watch-form.json @@ -0,0 +1,354 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": true + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": true + } + } + }, + "energy": { + "joules_micro": 2000000 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d5f61493d0355f54008d3bc56cd23fee958acb2dc10ddf6f10d28c632c6a59e6", + "signature": "5f4d6aa5a15668d0a1369b087ee13495ac27c0418b8b7715b32a7a9d605d7d250dc905d7f0056faf7ac3224a277194d7db0a23a7f331c2e6be5fe1799aa98704" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-form-cost-long.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-cost-long.json new file mode 100644 index 000000000..f3ace4d83 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-cost-long.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "11111111111111111111111111111111111111111111111111111111111111111", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "55ee6caf6d24ba3f5f48f373cafc67c43634fb6c3186f4b468a1a9852b6db726", + "signature": "002d6f760a23262c5c830722399f7c3ed0eea130423024b1c9d58847920034d2e7a4cfc5b7f339d3ad4d854646c714a6c420934b5263333d5b5ee237afc9070c" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-form-cost.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-cost.json new file mode 100644 index 000000000..9d20f2793 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-cost.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1e3", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "87860be8844677bbe81fc4bc5f468d3f0b887364a5a1891fa24a7d4e0d70adff", + "signature": "fcb08b3a964c6b588f9c91946b3b018ae4ad030c9d25a78fed304f7b5346ed27155f3dc59f20cab7ce3304ae6f5b972f4aaa46e417685e954d4fe795cb3d160d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-form-exactness.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-exactness.json new file mode 100644 index 000000000..53736a0db --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-exactness.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "nearly", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "b3f71c33c30f682fc0895319593ed53cad86dd95f0c71e2db0bdd898cd6fd09b", + "signature": "8a4253390cede8e06c4182d2adcc17aee77cc7776290c1513481db034a1519f79e51cf344954a08e6adb27dd08d0bf5347d260642bd7ee99ac335975c6104f00" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-form-member.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-member.json new file mode 100644 index 000000000..e1ad08180 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-form-member.json @@ -0,0 +1,344 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "deadline": 1 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "75b5af83ba3718bc14c58925b246ffcf8eb0d4e612c869a5c4f0bb197bbd06d5", + "signature": "12d2f38abf6b02ad41a268fc02f26ee004125f2af7af0aa0bb9b31e00ecd95e9cff728c643c25a6f14bdc9d4d580c26748779d8a0ce6fe6bd5f39675e49cb70a" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-host-providers-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-host-providers-other.json new file mode 100644 index 000000000..f39352881 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-host-providers-other.json @@ -0,0 +1,543 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "someone-else" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "72207a76a4132c47fc16379ad71ae19b1a0330d56af0f444f191398a3643463b", + "signature": "b4e5821cbbb4bbe9ac08a2db61fdd4be892dc0331ced5e9c7a70588843541ec83f042c86b774a26bc2526caa3478d1ce33fc3a7a2522eab1d6c4a6adb0fa1509" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-charged-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-charged-other.json new file mode 100644 index 000000000..7f2e8d74f --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-charged-other.json @@ -0,0 +1,450 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.01", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "ddaad12efd8d7b2a16a3dcaccec8d005a0187fbea011b5f4e3cb18cbd7b1a4ed", + "signature": "da9df33d567d113fdcd20c619604f9b6dee438d51e9baea100e4a0031966eaa0691b7f1a5967e1809bfac71f9c2e08933f90c8478c7cffccb8012676bb469804" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-dropped.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-dropped.json new file mode 100644 index 000000000..b6135bf40 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-dropped.json @@ -0,0 +1,335 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "a6f83a0d5d4d1a769ba3f1e2db4d9a6417f8c00e3585d82d441257f792f71807", + "signature": "40e7022dbadffd05aae25e5a29e2065fdaf72aed50d77678e6847eab924f0606364c4854e3b5f9d63ae2b3985f3a736c27b2d4ada03cee4a3f4a449310149d02" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-elapsed-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-elapsed-other.json new file mode 100644 index 000000000..fe683604d --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-elapsed-other.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 1, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8dd8959ab32364d5e927566f4e1cf77bedc26a138a998c5f84e23317ec09bb68", + "signature": "f4974d82a25391158162bef96264451f50c94542e27df98228350d1d835d42a50109e06d2b50fd0cb04d1a355a1ceb5c92152faef8c259555443b109f21e280e" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-false.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-false.json new file mode 100644 index 000000000..248fee9d6 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-false.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": false + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "10370223839248edc04f691d7b95d1f1b111f44c137679a6646cdffa5d5bd035", + "signature": "2dad42ca503e3fc4b3874107fa51e2b0055aea9986e6395f93d3c6b14ade5c2ccb1b5347d29357ee693619b5c382920eeb7fcafd2da569376adf61455347520a" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-member-extra.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-member-extra.json new file mode 100644 index 000000000..1aab3cb96 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-member-extra.json @@ -0,0 +1,344 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true, + "note": "on time" + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d5ca79f464f00ecebbba3dbe80eebe2ae26ca6d9abc35fcdf2865d0bf93d6401", + "signature": "46f56f583fefffa65d114b8470465f08f659f8a4144a5ec6a8451def1d875d56cf44db95e39826809d1a93bcf8714ef7d7b792eddd470d268fcd0a08c37ad903" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-missed-stated.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-missed-stated.json new file mode 100644 index 000000000..80f3c05ec --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-kept-missed-stated.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 61000, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 61000, + "kept": false + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "4d5f6acd75e7da2a40a36ec202607ce18ccf2256b9593fc73f25045472e7ae76", + "signature": "ae1af272a9c200ddaf1cde1925d3eb310f04e5578bf24947b799c6469b80e41673766123025df8387962e85e722458ceb50232aac8b62803a4c4a2726976b501" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-local-money.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-local-money.json new file mode 100644 index 000000000..212a2c015 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-local-money.json @@ -0,0 +1,345 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": false, + "amount": "0", + "currency": "USD" + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "34470ed056c05a01dd3fbac948ae9e73ded8d8839f601886cc36198b01f35296", + "signature": "5427089f2905d463a4b6a510c655b7b10917bac7df07f3fb4304f0056a39b30d25a0eaff2e001da8ac1386b32086c80eb75a9833c90704411ad124649bdd050f" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-memory-at-cap.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-memory-at-cap.json new file mode 100644 index 000000000..3ddccdc42 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-memory-at-cap.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 17179869184, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "afdfa4976b218bf5529c2e17e42dd4a824e3227a5d053c5c01765fb1da5a7d19", + "signature": "723e21cdb1b963daccdebef8adefb59f5243c0cd7355d8589cd24798e872c3cf8b5dc868ef7ebaf119b574ea608d8d72f87f8e6cfda3c70bd80a6f7d123be80d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-named-approximate.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-named-approximate.json new file mode 100644 index 000000000..85ed9e853 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-named-approximate.json @@ -0,0 +1,451 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen", + "approximate": true + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "3c033b370d47efec1066305384cdef56dabb468c32f0700450fc29cdb585e5f3", + "signature": "a2b107e198584b95e29622573061090d1597246ade1eaaa71dae6cfab0814a7ee37c6db1dbaedfd0462806b0d09297d361db7aa842b728dc24abc4be99d5180b" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-named-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-named-other.json new file mode 100644 index 000000000..352b29c79 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-named-other.json @@ -0,0 +1,450 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "providers": "allowed" + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": null, + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "16dee06551ccdd2d87094719105185f33e94bce3ae2314bcdbb3027cc52b927d", + "signature": "b951de24191d26a16f04fd37e5d792da1bcfdb4b8b310639da7fda86a2c74723fcf357b9ab5b794e38e00091a0297bf0eadedb97bdd7ec0f1ee6d9a2cc728205" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-format.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-format.json new file mode 100644 index 000000000..bb09202a4 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-format.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/2", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "4f13bbcc213af6a5dfc672e063f3680ea4f2f0f721e0d6c98b6675289147e723", + "signature": "0aa091dc31dcc7796db33c55afe722a035fcb15ceda1acbe7918d337c25829d766f1797c91b001122996b8a15b8df46ceaf42823431096f60204f3f2888c5608" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-missing.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-missing.json new file mode 100644 index 000000000..467296bf7 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-missing.json @@ -0,0 +1,53 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "31fbf6c42cea955cf95cdb31f0f719cc0c58f75439d234cdcf1f14a18b5f3ddb", + "signature": "67a78a0cb81b864a403630042d9fb653576185af190a2696398828cfe35996f5c00769a0caa236fe0b7a41bdf88eb871a3ffc9526ed52d094e37c65171ab0506" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-on-plain.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-on-plain.json new file mode 100644 index 000000000..de9fad35a --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-on-plain.json @@ -0,0 +1,351 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits", + "estimate": { + "memory_bytes": 67172870, + "work": 2016 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "observables": [ + "Z0 Z1", + "X0" + ] + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "expectations": [ + { + "observable": "Z0 Z1", + "coeff": 1.0, + "value": 1.0 + }, + { + "observable": "X0", + "coeff": 1.0, + "value": 0.0 + } + ], + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "cdefbe5e97db7d9b037a7aec6ddd172bcd7268b2739ca6c0677c46a3c22235f1", + "signature": "7e749e768f65aa90267ad84bd416bd1d23fa01ae04213a38010ee7318baafa60c4c88cb40e3b7a447f1435669f8a16fa1b297ed74fae281cac8c0b75e85f1005" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-wanted-from.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-wanted-from.json new file mode 100644 index 000000000..61dd2057d --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-wanted-from.json @@ -0,0 +1,312 @@ +{ + "status": "done", + "method": "exact", + "why": "bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "estimate": { + "memory_bytes": 134218112, + "work": 40 + }, + "request": { + "qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n", + "shots": 500, + "seed": 3, + "contract": { + "deadline_seconds": 600.0 + } + }, + "result": { + "method": "exact", + "qubits": 3, + "gates": 5, + "accuracy": { + "class": "bit-exact" + }, + "state_hash": "5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5", + "counts": { + "000": 254, + "111": 246 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "bit-exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:exact", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2e-07, + "basis": "nominal" + }, + "memory_bytes": 134218112, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 268447588, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.024723456, + "basis": "nominal" + }, + "memory_bytes": 270794752, + "work": 16482304, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants bit-exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + } + ], + "choice": "method:exact", + "why": "what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 600.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "7d9cda3a348962cb6acd009275760b82288d9ac4e75ff94a7956b5c2bc0b2378", + "signature": "74d566c7c7397c303cc429d9fd0de1b884fdc3f528729fe55ab7106aa83d57b063e1dbf4120dcc091fc6451d838597288444804dab8ac89630bb87242bea090a" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-wanted.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-wanted.json new file mode 100644 index 000000000..992671a4a --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-planner-wanted.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "heuristic", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "92cf9b69f493f54742138a83febee1a9366d765301d9f77c1cf75d8c50c61fbd", + "signature": "4959b8a99e9c11fb8c3e68a342d1e20b315b9ca9172badda54818d6dc65c1cd96c8b7211494539f25ab08ef4c752a2d13b39d7a50454b8bde9918f37b8e05f0e" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-price-amount-long.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-amount-long.json new file mode 100644 index 000000000..9686ceb83 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-amount-long.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "11111111111111111111111111111111111111111111111111111111111111111", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "95675d2db7469f09ea93183572f7b02549d1b6ab8fb9a73d7c00424d2867d115", + "signature": "0f1b72780bfcaf25fa169581b8a4c634d288e17f76e86ee7bbcc368476d53afd8f2b115cd8ae6f3d32321454d1ce52ddfaca6b050328aa6f41a851b93fad0c0e" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-price-memory-null.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-memory-null.json new file mode 100644 index 000000000..c4da63d49 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-memory-null.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": null, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "2c019f7c04589a39b9fec2a6d2528df7d6377d8f3282448efaeb3475d02a4447", + "signature": "79eb96edfdd5c7650d3bc45a0b7eae317df7eec141d1bff9f7bc280a14cdd2e989db9b7ff2ed70e4762859cc0214cb02f8d9bde2689a8571ef27b6e783af6e0c" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-price-provider-memory.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-provider-memory.json new file mode 100644 index 000000000..24072251b --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-provider-memory.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": 1024, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "f618c6f0098c2d65dcbc8084b0a00c93cfa21b06f4e3a882b353dede692c80ef", + "signature": "4e1aaa87fdda1240b3d411b433a2fcc1515dfef24c27748804911947898ac7f2aa0377f388bef416074fe79ae8b85cdb5c9a5e92a98af32ae6ed7feeee12cd02" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-price-seconds-past.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-seconds-past.json new file mode 100644 index 000000000..9d630170f --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-price-seconds-past.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 10000000000000.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "19c76e2aeade97d303576afa32e55f3e1de7439b0a0757dd101c1a6754bc9fc9", + "signature": "30b1568f0f5e9579053b2ebf4d97f278300625d612a10e4487c5b1f8770a0599eb8729589eda4a3bf4596859f985683e7c6ffd6382f5c8c62ebea1fcde6dcd08" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-provider-named-not-allowed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-provider-named-not-allowed.json new file mode 100644 index 000000000..92c6d18c1 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-provider-named-not-allowed.json @@ -0,0 +1,449 @@ +{ + "status": "done", + "method": "provider", + "why": "on priced, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "max_cost": { + "amount": "1", + "currency": "USD" + } + }, + "provider": "priced" + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "c7626c0d9f68fe8e420df9cfe19f635427160bfe4902af2cc12c480b28d3b439" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot", + "seconds": 0.0 + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "named", + "named": "provider:priced", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 17179869184, + "providers": [ + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + } + ], + "choice": "provider:priced", + "why": "the route the job names, which meets its contract (1 of 14 routes)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "42dab8b20f638eeb9c1d46fd7a0890b574c641a1e11d1306da2abc201ca84c5f", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": { + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": { + "amount": "0.09", + "currency": "USD" + }, + "kept": true + } + } + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "5457b269284d4b4d29885508227abccfb634705b295c810d473c7aab923e3a24", + "signature": "c0d647ee7137bc594eaa005c6f206da08b24b5449aa0945670447ed5e1d1f35982b11906c483bcad3bdb2e7d8637617c622d373e81c5882500e5071a6d39a20f" + } + }, + "id": "pj-e158396f1fd8f81d", + "submitted_ms": 1794033072602, + "finished_ms": 1794033072605 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-provider-not-chosen.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-provider-not-chosen.json new file mode 100644 index 000000000..d8d399ab6 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-provider-not-chosen.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "priced", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "106a024ec66679717d951e9a841a6b6f10469238811d31ff7587bf964221752a", + "signature": "26c1542acd6cb9632be2a885b34be090840761a8658df4965ea73bff805ad5af76487485445be454c365ce564af2ded296a1f3e70ac01f0e195794e8f739f701" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-providers-not-allowed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-providers-not-allowed.json new file mode 100644 index 000000000..df8f4e1ae --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-providers-not-allowed.json @@ -0,0 +1,543 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "efcb8e61a35a909ee4ef4add3edce0131fb6c79e6a74daa72407f6932e1bba83", + "signature": "82af7c4478995abef9e4f12222f81b956c90a45a666a9b4168d11187fc22158a24d7a52eeccf2e6021e3f50c1c16e00210ed03d7d44297924dad2b0bf427600e" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-question-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-question-other.json new file mode 100644 index 000000000..10f35a080 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-question-other.json @@ -0,0 +1,312 @@ +{ + "status": "done", + "method": "exact", + "why": "bit-exact state vector of 3 qubits; what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "estimate": { + "memory_bytes": 134218112, + "work": 40 + }, + "request": { + "qasm": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[3] q;\nbit[3] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nrz(pi/8) q[2];\ncx q[1], q[2];\nc = measure q;\n", + "shots": 500, + "seed": 3, + "contract": { + "deadline_seconds": 600.0 + } + }, + "result": { + "method": "exact", + "qubits": 3, + "gates": 5, + "accuracy": { + "class": "bit-exact" + }, + "state_hash": "5f1ae3e98c0555290986daf0d573de16a34ba01d1993f13f134e0b1daf6f1ab5", + "counts": { + "000": 254, + "111": 246 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "bit-exact", + "wanted_from": "auto", + "named": null, + "question": "amplitudes", + "auto": "method:exact", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2e-07, + "basis": "nominal" + }, + "memory_bytes": 134218112, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 268447588, + "work": 40, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.024723456, + "basis": "nominal" + }, + "memory_bytes": 270794752, + "work": 16482304, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants bit-exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants bit-exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants bit-exact" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants bit-exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants bit-exact" + } + } + ], + "choice": "method:exact", + "why": "what auto picks, which meets the contract: the contract names no class, so it keeps auto's (1 of 13 routes meet it)", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d859d0ec175157bdd2b0e221a569afd4d2d94e347cbd550027c714ab35bdb061", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 600.0, + "elapsed_ms": 0, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "284244ed02df6c6f31e2bc4ed41553bb04d1878f6c38c14c4186941a92c76db7", + "signature": "db84d76890b160ac506199f085ceb9cd753aabea3d25395a41f07acc1155b029f66e1f835947ed1d4bca5dff1ca588b65d8c82146d90ee96c03038f42464c201" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-result-class-foreign.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-result-class-foreign.json new file mode 100644 index 000000000..2260ec379 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-result-class-foreign.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "bit-exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "de187e27decaf890ba2e96ac57bc908087f76bd4917fb6ce7e5cfbbbf453addd", + "signature": "abf8ec3aea805b1e7e7e72d51a00456b9a57a1a9d18656f8f4ec1ebf521a2a54d0e7f42699aa0445e361c4782ee50dd138d5b787129b2c08dc4969870a30760c" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-claimed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-claimed.json new file mode 100644 index 000000000..014d5e0c8 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-claimed.json @@ -0,0 +1,339 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "f6695d9e18b8a7defbd23c1bbf45569fb661d8feb125c2049b55d6c803ab6238", + "signature": "35c23ba2e245b387b55540b386604d6ea485c33c44bdae1c1e2f848979287cfa83862b55170a6e49ed42facdea3496529a4bab166db5942f347b43ce70988d00" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-class-by-job.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-class-by-job.json new file mode 100644 index 000000000..97f9872f3 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-class-by-job.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "estimate", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "b8c7e82812f75a33dcb1bce744afca76b17b326ee25f94bd142713d554f42c36", + "signature": "f21b33c936bf314d82630512231f6a287ff8fc48a8736ac1b8caa065e05e354eb8a82f12e0850c480f8575a0c547b176896f50aa3e24713f49e1e17b9d514a0c" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-class-gpu.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-class-gpu.json new file mode 100644 index 000000000..c7dda034d --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-class-gpu.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "exact", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "f59a50c43a5bbe79f98a8eb2b6316a7659789c464a41cfb86898be3338427607", + "signature": "9a93e7ac6f88d85a2b5e3f8a08b1f99d5e0ea89f6116950085dc91e6cc90ca37ed5d07c8d40527640ea511aae01816bc213218b4797100c1b0fcf070ae6d4906" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-code.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-code.json new file mode 100644 index 000000000..2b16c2d57 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-code.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "deadline", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "71da1746a71c876b9b5263ebafec511337f3d864007f416b03ff443793388afe", + "signature": "cb1dca70e379cca904a26b56a401aa6a308676055e64a8de730c350df482e2f277a527205e77c76a908909e235ee6b547862ea4ec1271d98e68bd04f7c65530b" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-device-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-device-other.json new file mode 100644 index 000000000..33e91dcc5 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-device-other.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-6", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d82682124f0c714c884ff7a616a9190e21d2aa5a420a4b580bac57dc26e3ad5f", + "signature": "72fc4ee6b1fc959b81d35167e07c311c6b9c38b7cac830afe261081d0e1bb5973f73b5f36a091758d4620d0d1ee4e5eb4dcd90cdf49bb7dd338175e645fda709" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-host-dependent.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-host-dependent.json new file mode 100644 index 000000000..9b70408f8 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-host-dependent.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "2aaa878a1cd4478d73c11ba5a924cf8224bf3f0903e558b7f87f5bf5a24d17cd", + "signature": "7f67e87bc54c328cdc4318be9b8c037fd8cf93ee273aec9f7349ba9699af6e330d23f6c907ec48616c15f3a2e89dbfa787a585f25bbdf2a4c718a6d2452ad703" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-mps-exact.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-mps-exact.json new file mode 100644 index 000000000..4cdb37f14 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-mps-exact.json @@ -0,0 +1,339 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "exact", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "bcd409cd099fa60358916a688c2174ff60ed947c6bd200f23c83c121f8821746", + "signature": "221ae0aecc89f0c939adf7c0ae55cdb7952a94d3cdbb6a4f81f372fb639230fcf6c4687aac5282ba139bf26ce2b9befd8ddb64760d3c293f71ce6869ee8d4506" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-price-memory.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-price-memory.json new file mode 100644 index 000000000..2580901f2 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-price-memory.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 536870912, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8cf1491e17a9146e045da96684b36836c097415f58ce004da2c5367666dccc33", + "signature": "8187b36ffb9a74327eb6bd8cda5917404f8adadf468a62b36cc584ad3cd413e8909cadf661b6c5de8de6a0fb294e78f5ac4485ff21cc2691042bcddb1468760d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-price-work.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-price-work.json new file mode 100644 index 000000000..65f042b97 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-price-work.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2009, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "6be0a80d6b7382e1026691f03a808ed07946d20ff850a63b7b898916309b175c", + "signature": "5489756dfcd671ad099dc88f3739bc19e0d273448092e20070b409bb12f26f23db59fbd45bd11f0ed2f6426dbe05bd8e3abb7e7eb3e17152462d5debdada410e" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provenance-class.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provenance-class.json new file mode 100644 index 000000000..fa6deb70e --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provenance-class.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "silicon", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "9dea6d0afa446cd297a4ab16999f47bcf4245b41f6cc95db12cf436116e256b7", + "signature": "bd7c45bdf52ee229a598e19006c14bcb2ee93fe10c3b9406f3e7ed6fafacf3820a863098ff3454cc3dce1a8aef5b68528f71a00f4b73b831365047d05e75a009" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provider-claimed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provider-claimed.json new file mode 100644 index 000000000..5c3423960 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provider-claimed.json @@ -0,0 +1,540 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "met" + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "90279f3317f606c223b9d0036ab8ba38543630d144bee86ac73da6946190348a", + "signature": "b0979f55f6410a2557aaacc4cd7fec407311861d761e04f6679030d759be8504252f09747c3e0b430082bdab044e79aad443d3b48fc336d6ea25fb5fa25b6c00" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provider-host-independent.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provider-host-independent.json new file mode 100644 index 000000000..0954318cb --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-provider-host-independent.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": false, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "0f80f41049e7d36fe2eb45823e6715c3a2411ccafdc09c9f90aca759302ae08a", + "signature": "7dd34bf8f72237c6185bc80cd66cc7b14ccc8e31c8e95b9af30b682e4d8ed293601439268305c7b639e616cd53d1bcb40bfdbcacf059dbae596720f6c2abda07" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-route-registered-host-independent.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-registered-host-independent.json new file mode 100644 index 000000000..1194d6e32 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-route-registered-host-independent.json @@ -0,0 +1,368 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:turbo", + "kind": "local", + "method": "turbo", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "dd82cdedb5d5cbf9d3cde5c2d407ab831e5ecfc2832149a587c259e83d324725", + "signature": "a9c3bc551b1e3c0bfe9c9c15d496ab6892946da20e1c36a85d18ecce335c4ba2ece1bdcae972c720d7e9e2e9c8a98c190a7f7d16cd586a8360aea2c150770202" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-bound-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-bound-other.json new file mode 100644 index 000000000..6a68bac8c --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-bound-other.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.01 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "139bebf92be7a7871cd2c87f0907a3b99185a45e454c7b703e3be932de34b512", + "signature": "411241bb7b7dcda3797437f02a7b4386954e306b33b3a1ffda7da183d3bd8a4ac6af2b8cd72409d3629d076af9ee6e8a2d4186431b61a845957ff3f109e93a06" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-class-foreign.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-class-foreign.json new file mode 100644 index 000000000..b9eba23fd --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-class-foreign.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:mps", + "class": "heuristic", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "mps" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:mps", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "mps" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "e278bbdf50e8c8f202aaeab7db2dc1e8b0ed5e203d3359f86deda7b2962bdf4a", + "signature": "c3c16c5544d85e3b23f82cfb69b0df552c581dc06327c82b89658c13c74e7c72388a01cf7590a56c690ad57fabde599ed95ced04c02666f12363d0640b79d707" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-fraction.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-fraction.json new file mode 100644 index 000000000..2a34ffd9c --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-fraction.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 160.5, + "11": 139.5 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "06ded9f40cbc79002c4a5e0b38886b91ff2e0c4125d07f7887dcbd26825dc745", + "signature": "121390ef6e78d718c930f8d2ddc0ade35e88f90de72b3e904b9ec74ff6af39118c2fedaf46568daa3ab8435cba12cbb11b22920f55e207792bc44d8ee3166e0a" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-short.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-short.json new file mode 100644 index 000000000..4c7cc63ad --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-short.json @@ -0,0 +1,540 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 1, + "distance": { + "computed": false, + "why": "a shot is omitted" + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "0bb468ef63f91978029f98f3a27f85c1af2fb879b6376f2624e9987e2aaaf1c9", + "signature": "61523dd3b3a93da79bca41d411e494e280293f3b73d3b12862a8d7dab30b0af19419128a10af408513e9f0925455a281de94215357b1bb19c3dcc8b1fd9fbf01" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-sum.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-sum.json new file mode 100644 index 000000000..897684c63 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-count-sum.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 162, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "5a71d7b2f95d9e8177322ec62edb700e6dbbdcd6ef31589c846c4fbda66e41df", + "signature": "769872dc617089401cd5e5610b1f84548ae8db33a1078edc93e9ecce88dbdba31c7214a7230be6d2e3e7c04379ab2602ba93f9b0d3343ff8582f69f9866f3405" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-distinct.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-distinct.json new file mode 100644 index 000000000..937931bcd --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-distinct.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 7, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "719bc67c37b909860b07d9c2fed9ff228906a3d89775ce53544302ebfb455d85", + "signature": "10ed44e40b3b5c69e2427cc73b77b1065b4dbda9f46afa740972e2aac63f99191355ac7e1613f27334881f69fd5530fffb14cc5ee562eea7bc53d80555a96a0d" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-missing.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-missing.json new file mode 100644 index 000000000..6a558f548 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-missing.json @@ -0,0 +1,515 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "13d9ed31dd4b470c0faa8860f4f4c7204fa57c31f15ecab5143370880e91cead", + "signature": "51c78059c14776ec04d14e98349c8155e33b304bdf747cf023211c8abcaf206bb89a963eee1369e13b0f250570d951f0337562636dc4b39178513ec001ba580f" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-not-computed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-not-computed.json new file mode 100644 index 000000000..f7bab7c99 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-not-computed.json @@ -0,0 +1,540 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": false, + "why": "said so" + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "379d167b6c8baefa93b39036b5be13abd1da2d0b6ed601b824d7ae2a0ea8cd44", + "signature": "f71eed95f50de214b1ee6daa2166d2fe0eef384b54f12dea260d7e2c20e3f41214c2a76577c5cb0259a6215149ec3b13d5eeac57ec610e4cd160f480953e8708" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-numerator.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-numerator.json new file mode 100644 index 000000000..895425b57 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-numerator.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 45, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8b8c5a84ab1a5c0076b992e4929d6397cfa8ee55899bd39109277b3700cc39f3", + "signature": "7a243c18b9d1f35053dbeb1ecda4449eabbdc828cf9e413df572544439ed2c4d411b6fb5b3790fad9a97ef181ad561c421438c09a20cd52174b705d294841606" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-omitted-spelt.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-omitted-spelt.json new file mode 100644 index 000000000..dd20f20d4 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-omitted-spelt.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0.0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "71770ed37d2687b9f97392667c58c80a80836d6852619f0498aa1dcfec9e4996", + "signature": "ffe2160d7de0f0939ebb0146de12a9617976cff8049ab415f5ce85b3964cf66cdc3a3f216926f69820f2b6d9d4ebe0b206442d1e6aac5931bf27d2808671e508" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-on-local.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-on-local.json new file mode 100644 index 000000000..6b9d94a65 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-on-local.json @@ -0,0 +1,348 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "shadow": { + "ran": false, + "code": "none", + "why": "no provider answered" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "cf0132dbb0ef03db8cc2e383293922a4f360da9407170d3f6b80c82fcfb5feaf", + "signature": "62c27500f57bd70edabb88b6efed23d8d61c6ff6a7e7341e81138d579367187ba93ffaf17526223b90b5adb7ff707ef5cfb600fb55f6613eecdc6a6ce9f05401" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-on-plain.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-on-plain.json new file mode 100644 index 000000000..a9b5fa845 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-on-plain.json @@ -0,0 +1,66 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits", + "estimate": { + "memory_bytes": 67172870, + "work": 2016 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "observables": [ + "Z0 Z1", + "X0" + ] + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "expectations": [ + { + "observable": "Z0 Z1", + "coeff": 1.0, + "value": 1.0 + }, + { + "observable": "X0", + "coeff": 1.0, + "value": 0.0 + } + ], + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "shadow": { + "ran": false, + "code": "none", + "why": "no provider answered" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "41752598a89bedab7bb51e517bbc0a2219e48eedadf3c796b58276349e9834f4", + "signature": "a407363b148b44cc99bc9dd5441eab9ee1b15c3f28b2ca78f17e7492ac17ec8e44482e7b44134bd8067a4b332ba0994afdfbd64bfd1321b4a4eb75662b7f5302" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-budget.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-budget.json new file mode 100644 index 000000000..b92a16783 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-budget.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 299, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "82f19196eb1672c60150b757be1d749c84d877865130f3636646a275bbcdec4f", + "signature": "2fa03a7fb3a161d62528cf23938b754ff608314ddbbf2467e0c3c35ef17b79a1f54814e2b55f147f67b111b335739207b2b9f70fc066ceaa7206d8a7f862560c" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-class.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-class.json new file mode 100644 index 000000000..b4640b24b --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-class.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "heuristic", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "496936d31fb2b0336b14d3b4d9e3cdcfcb1236707573d3f35b698b6cfa953b98", + "signature": "ee2d077e5bc1cb4d5a6aea31a46f35aafcdcdb5e1f5163afab7bab014dc48a5c3500f098abec81f51ecf5a785e35f8cac241eef8a45f7880deaf23d469ff760d" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-code.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-code.json new file mode 100644 index 000000000..459f7cea7 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-code.json @@ -0,0 +1,498 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": null, + "code": "failed", + "why": "said so" + }, + "kept": {} + }, + "shadow": { + "ran": false, + "code": "failed", + "why": "said so" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "ab26c9537e838cbc6a9c9644e4c58d5b2ede4f59ffa6b98f907312f9b161d719", + "signature": "7b5228b3e105f8ed38f98a9d1412d64bfef5d99a6755113ca387204ab6c7f17767745240a3a6c427cc72d633106681481b7ad1b81277f8b9f7f614156d41440a" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-missing.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-missing.json new file mode 100644 index 000000000..5dd38a3d4 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-missing.json @@ -0,0 +1,517 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "99ee8071a7053f185308369d7c2d3053fb48be1810bae3620b9db18309da112a", + "signature": "186f1fa8390f69975387fc83797ee1963ad245d24ea675414138677d06935f15af6c6542732d04deb6178229799e3bb23436b6fcea985cf5d2cb6e87e6d5b905" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-price-over.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-price-over.json new file mode 100644 index 000000000..11b442d00 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-price-over.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 301, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "cdb68c5f54a38f3cda0086b77cd3a17bd34d386478bc76e6eb31baab8f8444da", + "signature": "b863211c9e7458ec68c9fcf394bb164c94cb0b03633f3b2fa23fe3ad94737c329b4e27eb1bb54a84dcdda341b87d1f91cc4bb3393ea17743ae9e38d9a6e72903" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-route-absent.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-route-absent.json new file mode 100644 index 000000000..18f09e634 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-route-absent.json @@ -0,0 +1,497 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "code": "none", + "why": "said none" + }, + "kept": {} + }, + "shadow": { + "ran": false, + "code": "none", + "why": "said none" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "374eae4f0b7be3a9abf7d6b273f986b3836d5f81b3a0093ffe393b8759afd315", + "signature": "60c49731de91da7900db1c82c0428391866e50d63a0dbdd05a18a5baf17c072e7007657c522d77812c66a2639df213dc4b44bca5782e2577d7f50f8d2e4fc907" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-route-missing.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-route-missing.json new file mode 100644 index 000000000..07e30e88c --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-plan-route-missing.json @@ -0,0 +1,543 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "20bf264048dfc3730c5005b0f19dd228b7e47b1cbb8c24f963d233472eff5433", + "signature": "d4e6431979ef31a25be0ca0abfbbabb923da30b3f2cc5d06b1b4693b124d169da0a250b0df1d745e253ddccc2d90ee006514aa4160425d005e1fbeba79c6bb02" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-request-extra.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-request-extra.json new file mode 100644 index 000000000..44599a17e --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-request-extra.json @@ -0,0 +1,550 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact", + "noise": { + "depolarizing_2q": 0.2 + } + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact", + "noise": { + "depolarizing_2q": 0.2 + } + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "9780bf1d6ba03584d20f5dbd238710bd569290fbb350d0c9fb5bb429f90cd92b", + "signature": "c1c439c39fea7343ce0ea8fa3d004c33cca34caa82431adc0292acde520f72f8b5e91852664986c49e42e95b3e391a62fef5a1f354a3846680fc00125bc0c00f" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-route-missing.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-route-missing.json new file mode 100644 index 000000000..f11287e51 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-route-missing.json @@ -0,0 +1,543 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "f444295186577e690c802c357da08d2f36288ce28bf5bf816092d08b5aa90731", + "signature": "b2485daa7cb1ff6fdedaa0ca71c61d9cb01a9b2248e97c67fb69157ba1d49a75d6b30e19884db85f55fcf69c2ec78c12fa625d61f0bd282d159d07d733095a03" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-route-provider.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-route-provider.json new file mode 100644 index 000000000..8b8e04237 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-route-provider.json @@ -0,0 +1,542 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "provider:ref", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300 + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "provider:ref", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300 + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8237aa60f386c5de8997854a2dafa89473da27c795e662b9e3e03353fdc988cf", + "signature": "c3b623c0b6013d644db0d1b4eacf368373e7a75f50e7d9a771933d22d1c2ff0f38a3ea8b69668e671e3009022a8a37f4b91745e41598e562546d0fb7d4c71208" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-said-failed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-said-failed.json new file mode 100644 index 000000000..f77b0fe66 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-said-failed.json @@ -0,0 +1,520 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": false, + "code": "failed", + "why": "the host says it failed" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d4acbe130f23abff038dafdd2badadb3b55a0a508ee15cf2db1066dc24c97358", + "signature": "e6dcf4695c5e903911ba37897aa518690059b4b0bb166a24d50bd0466f99baa8fe86e3c457f5b49fd85d513ffefe94f3e44514d1d2afac31854628c4f6b56300" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-said-none.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-said-none.json new file mode 100644 index 000000000..517c380e4 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-said-none.json @@ -0,0 +1,520 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": false, + "code": "none", + "why": "said none" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "db1833bba02f01d09ad14e8199dede5bf1387ab7c14f3ebecad33649b36c56d5", + "signature": "bcbcbd47d2cb90720e376de4dd53526f65ab41c060e2bdc07d44d5adbe5e5ed364cf5a42e41de7d316403548ecf7d33a22a4bb9cc6a1fa55985eb6e141b22207" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-seed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-seed.json new file mode 100644 index 000000000..30ba33ad1 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-seed.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4, + "method": "exact" + }, + "shots": 300, + "counts": { + "00": 161, + "11": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 44, + "denominator": 600, + "total_variation": 0.07333333333333333, + "hellinger_fidelity": 0.9946222222222221, + "sampling_tvd_bound": 0.04602751441903442 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d38df36251cec0073639413fcdc0d980a9ff855c264147735acc771e1c9c01d9", + "signature": "d58f23d423b717248aa8ec599e3b50554214ffa7d5d6958af6ce56da4defe68bfd604c2ffce733a6da7bbcf3169acb11ee72cb8e1ab6a730130b90b6c75c4e01" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-width-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-width-other.json new file mode 100644 index 000000000..f0c4dec49 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-shadow-width-other.json @@ -0,0 +1,544 @@ +{ + "status": "done", + "method": "provider", + "why": "on ref, reference:line-5 (wai.quantum.provider/1): compiled exactly to rzsxxcz on its qubits and checked by simulation here before it was sent", + "request": { + "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", + "shots": 300, + "seed": 4, + "contract": { + "exactness": "simulated", + "providers": "allowed" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "simulated", + "note": "counts from the provider's simulator or emulator, as provider.provenance names it, not measured on any device: classical software's sample of the program, read as counts_source says; they show what that software gives, under whatever noise it models, not what a device would" + }, + "shots": 300, + "provider": { + "name": "ref", + "kind": "process", + "protocol": "wai.quantum.provider/1", + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "qubits": 5, + "basis": "rzsxxcz", + "describe": "0a802ecd608fb5bca73c5a22ff65b5a08a408416501bb5472986f6540ff91ac0" + }, + "calibration": "reference-f2d9fe570421", + "compiled": { + "basis": "rzsxxcz", + "program": "b96b3d2e44387bac1dab89e43e29706788b0b6ed721f88d5c0f64be293c72df9", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nbit[2] c;\nrz(pi/2) $0;\nsx $0;\nrz(pi/2) $1;\nsx $1;\ncz $0, $1;\nrz(pi) $1;\nsx $1;\nrz(pi/2) $0;\nrz(pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description states no errors" + } + }, + "job": { + "id": "ref-1", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.03666666666666665, + "hellinger_fidelity": 0.998653743148044, + "sampling_tvd_expected": 0.023032943298089033, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": true, + "estimate": { + "free": true, + "seconds": 0.0 + }, + "charged": null, + "confirmed": false + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "shots", + "execution": { + "stated_by": "provider", + "mitigation": "none", + "twirling": "none", + "decoupling": "none", + "remapping": "none", + "optimisation": "none", + "verbatim": true, + "note": "the reference simulates the program's gates as written, on the qubits named, and corrects nothing" + }, + "counts": { + "11": 161, + "00": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "simulated", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [ + "ref", + "priced" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bit-exact, and the job wants simulated" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268442722, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 7.296e-08, + "basis": "nominal" + }, + "memory_bytes": 67128070, + "work": 608, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.010518528000000001, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 7012352, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and the job wants simulated" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4.05e-07, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 2700, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants simulated" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is exact, and the job wants simulated" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants simulated" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants simulated" + } + }, + { + "route": "provider:ref", + "kind": "provider", + "provider": "ref", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "chosen" + }, + { + "route": "provider:priced", + "kind": "provider", + "provider": "priced", + "class": "simulated", + "host_dependent": true, + "price": { + "money": { + "free": false, + "amount": "0.09", + "currency": "USD", + "unit": "shot" + }, + "time": { + "seconds": 0.0, + "basis": "provider" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "energy", + "mitigation", + "decoder", + "charged" + ], + "program": { + "shots": 300, + "native_gates": 9, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "reference:line-5", + "provenance": "simulator:the wai-quantum exact simulator: the state vector in fixed point, sampled with the seed given", + "outcome": "rejected", + "rejected": { + "code": "cost_no_ceiling", + "why": "0.09 USD: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider" + } + } + ], + "choice": "provider:ref", + "why": "the cheapest of the 1 of 15 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "e42e49d90e3f5015f93e050136dfb3c2633235039d89e9db50114125c0aced1a", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "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", + "shots": 300, + "seed": 4294967300, + "method": "exact" + }, + "shots": 300, + "counts": { + "000": 161, + "011": 139 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 600, + "denominator": 600, + "total_variation": 1.0, + "hellinger_fidelity": 0.0, + "sampling_tvd_bound": 0.06521202331161233 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "5a907d30971e88ea738bc90e9b40706608717426530f29869c3efd4f075e97a5", + "signature": "bf5f5c993a9832ff147fb403ec1fefca7a5fe0d844a698bd54057748dcebf20ae4941f701f2c26c1a5a81a309dba4c833e4f72b4dadca584a879f0bdc649ee0e" + } + }, + "id": "pj-6059aefb7ace70bc", + "submitted_ms": 1794033072508, + "finished_ms": 1794033072511 +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stable-choice.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stable-choice.json new file mode 100644 index 000000000..1ca6c0736 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stable-choice.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "27d48e6f95f8e1f6410b97f3bc261718f2d25039c8bb06bb10b07dc7a73da472", + "signature": "ca040d0f1a083911779b78a943317f0abc8b2b004348493100581aa05094185fa55c6f5452c87f4807571a1aa16890dfc721aedc8f7f0afde7a11ea917a45408" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stable-digest.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stable-digest.json new file mode 100644 index 000000000..f41ace051 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stable-digest.json @@ -0,0 +1,343 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "0000000000000000000000000000000000000000000000000000000000000000", + "choice": true + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + } + } + }, + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "ff5a62adad1da042c06a3765383a7e0d71238f44f2337a61d5d017ef58c097a9", + "signature": "991dd5b2ffc95a1cdcfad1439e891989eb3945d5f0fbd0a507a3c3b9e4f20e419187847634b4f9386dde61ecb4c42ddc9f18de66bc922d0d3a4453b559c4ff0d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-at-ceiling.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-at-ceiling.json new file mode 100644 index 000000000..0459c1095 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-at-ceiling.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "d4660ef3d2106a738c2aca1f4a05a8e0aec99dc927d33051bbab19f3373fede4", + "signature": "bad262fe09d9c3fa125b3fbf9e4e7cbf402abb5d997ce814281d53c1dde9749997dbb207f9231944cda592165fa09bd34ce88d3bc4912fec54ec8736a31cac04" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-at-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-at-other.json new file mode 100644 index 000000000..9245d04c0 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-at-other.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "deadline", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "6942ebe36e3aa80ae0cc33743e0da7f3b9870402f04d7660a09508d2907851d9", + "signature": "2a30ea96bbef006c0ba66b6b251618a7e9c75eaf0075156fc87aeba7bb0c931cda171af70a95504a2b95c8685b2efd94befc85d01b7afc9f6ab086a26c786a06" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-class.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-class.json new file mode 100644 index 000000000..03e7b279b --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-class.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "df6f2188d5aac89ad55d4b6b04d13f791900381112cc1a902976a938780ff0aa", + "signature": "4231f2d1a1962ca7533648efcde9cf2ec030b3983871317d031b85e43b09429128d9570317ba08cf1971efa661fdcc921d01c85c21e68402bbdf4c154db57302" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-form.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-form.json new file mode 100644 index 000000000..a6458a8dc --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-form.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 1.5, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8feffd92d42fe36eb9473a219d7d4da3efee239f71eb5a71212ae1a00b6a7318", + "signature": "628a76f1971f7a1d9e5993c8f50ad479f3f20c6e00ffcc0e2e947a7399cb35b81c30c9695961381e7af11b57adec1bbc4c8826e766f82ac8a8159e0e1fa69408" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-fraction.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-fraction.json new file mode 100644 index 000000000..14fe1062c --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-fraction.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 1.5, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 1.5, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 1.5, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "fbb47d46159b5dafb38f7d99b857993993d8f465d746dec7b6445f05dfe72812", + "signature": "cac4da82cd1702f04c98b83693ec369272b1dcec6b02ca3d61c3855d1cd347f73c0fd09a9d9bfe516478d7647dbee0a3c81b1a21631706697f63e31904b89802" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-other.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-other.json new file mode 100644 index 000000000..33cee221d --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-elapsed-other.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 99999, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "939b7ec25ab9ebd2ef6069538627d3ce4887926a04448f98311dea7f6e98bb4b", + "signature": "7ee9a2626a8e2a8121513b952ea91859065ffba544c0bd19404235e89f3a8aad1188edd0800e244f94e5f3debaa65a3b25724ac2f94a86158d456d994092c00f" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-extra-member.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-extra-member.json new file mode 100644 index 000000000..27e3532a4 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-extra-member.json @@ -0,0 +1,356 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading", + "note": "more" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "9b9ccb58de2742812658ca22e2408e95762463c1d15196164c4c724d03f59b94", + "signature": "614a19db477315f64efab1d595b591607348450fd6bb2f2e83f6a6477708ba0d181ced525b3f5683a685eb2eea5b5f3b9eedfe5b66d68c0522ec50323fbd1b0e" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-kept-claimed.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-kept-claimed.json new file mode 100644 index 000000000..da666896f --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-kept-claimed.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": true + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "36f20bd49a8465be6af3df00a48a62d3da6716e0bd0225ac257699c3c5c7d4e8", + "signature": "40e467ac25d79c0d44102e85bbd3ec85882dc31dfdf856877ee980db2f8f2f3e9befc82398864803723a8ee65d22f4012d918caf156fc4e0195124b9c47aa103" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-on-plain.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-on-plain.json new file mode 100644 index 000000000..9c090811e --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-on-plain.json @@ -0,0 +1,64 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits", + "estimate": { + "memory_bytes": 67172870, + "work": 2016 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "observables": [ + "Z0 Z1", + "X0" + ] + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "exact" + }, + "counts": { + "11": 505, + "00": 495 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "outcome_dimension": 1, + "expectations": [ + { + "observable": "Z0 Z1", + "coeff": 1.0, + "value": 1.0 + }, + { + "observable": "X0", + "coeff": 1.0, + "value": 0.0 + } + ], + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "energy": { + "unmetered": "the command line does not meter a run's energy" + }, + "stopped": { + "at": "max_joules" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "4c4b4a85dad835e2c41cf7d2e8dff68247905b9c29d20f2a855dcdd366b15afd", + "signature": "4b19b348e1117ebaedf276bec9df7a701f1565b019b1a46e648cc72f5367bbb1adee42b70a773ffbdefffa194ee8648b2886c75040d00639216ab8459057a203" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-on-provider.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-on-provider.json new file mode 100644 index 000000000..ccaf8a7ed --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-on-provider.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "e55ec0622498d2dd45d6b54e437bd786a792bd140247814eab6d8af60e2d7a6d", + "signature": "097a515ba4450fbbf5bbc5369321dc76b12d1cb630c211fd0b535c26a3bfd94ddcb9aecdda464531512428b03c517886069795086c0a95bc2bee2c4880786908" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-other-ceiling.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-other-ceiling.json new file mode 100644 index 000000000..e4c3d2215 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-other-ceiling.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 9, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "271d66dd518a181a707a6a5fb0a317b78d32a9f02df7ec7710b056bb32f99808", + "signature": "6119231811395e57c9d510c5b455d40e63589545a64414b05a9218e250a392afc5af64e18b7903dc62d6a4f4d77c3b06028b74d1a1c2c9546c1717b045bb530f" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-read-form.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-read-form.json new file mode 100644 index 000000000..8e5d69220 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-read-form.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": 7 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "493bdbaea1036b06d7efa9e98c5f288d46cdca524f11553d2fc1e527d2f38726", + "signature": "2c868de85318bc75d409123b85f16c18a357332f3e85887037a447d18074ccb7e377f87a827854390de9bd2197e1a84efea61527543f452f1c146cb50136b10f" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-under.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-under.json new file mode 100644 index 000000000..92d4e8c2b --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-under.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 1.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 1.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "206d4a46d5f8a76abca3fd98651041581e1d0388ea9a87e8a9dd3faf95e5ad60", + "signature": "66ca03cc11c7a08388e9197e0d606d8aa12c45bb90aad8c7c76f2c86ba4266915824a9877beaa51240b1cbfdfe73093404a0f6eca9f8243a9e648e38fcabad01" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-whole-above.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-whole-above.json new file mode 100644 index 000000000..2b51dc1c2 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-whole-above.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "joules_micro": 2600000 + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "666018250f88cf1479b718fe6fbc77d0985d402c193cde448bb3ef75ba4ca947", + "signature": "f79c6bed73ad781d1ccebd791c606e85920f632573e9d85496d5f559685caa5ecf8bded8cde316b05428d939f3d51490dfb7a4676961d6bde5efb8fcd95c0a09" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-whole-below.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-whole-below.json new file mode 100644 index 000000000..ae37cddcf --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-whole-below.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "joules_micro": 1 + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "901f3a321aa6e0be9b96ea6ed52b666563825e12ba6a2af7d3a94061e36b3e62", + "signature": "388e5f529ff4dede9abbf2f2e263d7fe0c32e03876b5d327ed2282094f0b2d710cb6af5fa134ab4ea4244798d30c5a73629a796be577cfffceff21391d5e2b02" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-counts.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-counts.json new file mode 100644 index 000000000..c79bd9e16 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-counts.json @@ -0,0 +1,358 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "counts": { + "00": 100 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "8ccf93b12643d5b4bf91989e3aeb99ad0ad640ece8a1464b32a89cf7fb791702", + "signature": "081671598e37fbb729b81a3e831967f5950daba217c2b73995b5800e418d405477c2ca4739e87127d43f60617a7597ec064d7510bbfe9dc3dcb4fea696d8fd0c" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-outputs.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-outputs.json new file mode 100644 index 000000000..54d21e28f --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-outputs.json @@ -0,0 +1,358 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "outputs": { + "x": 1 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "6ee6afa1da2f9967cb3fd535c9217d78fbe885a3e1915cf9507ad31f589cd28e", + "signature": "b5949fd51d910e66108c279f93eed36a79e6498d7052adb1c8f6fb866ead8649846e2405f877f97f880e8f1b57e81fd2bdcca7abf76aa614692fa4805eaa7a0d" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-verdict.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-verdict.json new file mode 100644 index 000000000..c4a9dbde1 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped-with-verdict.json @@ -0,0 +1,358 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "verdict": { + "holds": true + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "0de3887f607d3ddd75dbbe2caeb9c683f7354263ab1e7d3bbadf333aa16f630f", + "signature": "9e19a821b664944e918e0356d28982233e2f987f17aa08a0fb4a808fe4b1789d55df9098a2c5d0420eba9196d606ac8861c494e7991600b16b7904e33a630900" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped.json b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped.json new file mode 100644 index 000000000..f0dd297a6 --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/crafted-contract-stopped.json @@ -0,0 +1,355 @@ +{ + "status": "done", + "method": "stabilizer", + "why": "Clifford circuit: the stabilizer tableau of 2 qubits; the cheapest of the 4 of 13 routes that meet the contract", + "estimate": { + "memory_bytes": 67172870, + "work": 2008 + }, + "request": { + "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", + "shots": 1000, + "seed": 7, + "contract": { + "exactness": "exact", + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "deadline_seconds": 60.0, + "max_joules": 2 + } + }, + "result": { + "method": "stabilizer", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "none", + "note": "stopped at its ceiling" + }, + "elapsed_ms": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "exact", + "wanted_from": "contract", + "named": null, + "question": "counts", + "auto": "method:stabilizer", + "host": { + "job_bytes": 17179869184, + "providers": [] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-08, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 8e-09, + "basis": "nominal" + }, + "memory_bytes": 268459522, + "work": 8, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 2.4096e-07, + "basis": "nominal" + }, + "memory_bytes": 67172870, + "work": 2008, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "chosen" + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 0.027721728, + "basis": "nominal" + }, + "memory_bytes": 270532608, + "work": 18481152, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants exact" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "stabilizer_rank answers amplitudes and expectation values" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "tensor_network answers amplitudes only" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 1.35e-06, + "basis": "nominal" + }, + "memory_bytes": 268435554, + "work": 9000, + "energy": { + "joules": 1.5, + "basis": "an estimate", + "watch": "a host's live reading" + }, + "leaves_out": [] + }, + "outcome": "met" + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is single, and the job wants exact" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "cannot", + "why": "density_matrix is for noisy circuits (give \"noise\")" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is estimate, and the job wants exact" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "class", + "why": "its class is bounded, and the job wants exact" + } + } + ], + "choice": "method:stabilizer", + "why": "the cheapest of the 4 of 13 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "30b5ed16af1556898b035da46b1d388aec9591b3194052e76020b1d83ce9567e", + "choice": false + }, + "kept": { + "deadline": { + "seconds": 60.0, + "elapsed_ms": 0, + "kept": true + }, + "cost": { + "max_cost": { + "amount": "1", + "currency": "USD" + }, + "charged": null, + "kept": true + }, + "energy": { + "max_joules": 2, + "joules": 2.5, + "kept": false + } + } + }, + "energy": { + "unmetered": "stopped" + }, + "stopped": { + "at": "max_joules", + "joules": 2.5, + "max_joules": 2, + "elapsed_ms": 0, + "read": "a host's live reading" + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "4d3779ca970d0a2cb6bd11b5e06e18be7ea3f1d4668ed4cd22c5865fd29e2ebc", + "signature": "5516fa6be72dd3ac3c82f9e5d063aea359e5c1d3b9f1a11a355825ccda542703b093d43ca8a66c1c70ca3280e0f751d5be374682e76a35e8c3fe88c865a30d01" + } + } +} diff --git a/wai/quantum-conformance/receipts/jobs/scripted-contract-prx-circuits.json b/wai/quantum-conformance/receipts/jobs/scripted-contract-prx-circuits.json new file mode 100644 index 000000000..4e3ac8ece --- /dev/null +++ b/wai/quantum-conformance/receipts/jobs/scripted-contract-prx-circuits.json @@ -0,0 +1,437 @@ +{ + "status": "done", + "method": "provider", + "why": "on lab, prx-circuits:test-qc (prx-circuits): compiled exactly to prxcz on its qubits and checked by simulation here before it was sent", + "request": { + "qasm": "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n", + "provider": "lab", + "shots": 400, + "seed": 5, + "contract": { + "providers": "allowed", + "exactness": "measured" + } + }, + "result": { + "method": "provider", + "qubits": 2, + "gates": 2, + "accuracy": { + "class": "measured", + "note": "counts from the processor the provider names, read as counts_source says (shot records, the provider's own counts, or counts rebuilt from probabilities); not reproducible by recomputation: the same job run again gives other counts, and no simulation stands in for them; what was set off at the provider, and what was left to its defaults, is in execution" + }, + "shots": 400, + "provider": { + "name": "lab", + "kind": "prx-circuits", + "protocol": "prx-circuits", + "device": "prx-circuits:test-qc", + "provenance": "silicon", + "qubits": 5, + "basis": "prxcz", + "describe": "1f6d996884468f37481db4e20932d6c0ecb84ebbbf4232f734080c61ab9fae66" + }, + "calibration": null, + "compiled": { + "basis": "prxcz", + "program": "12123632bbbc70df6b58c3103f50479a72211ba109a01d9e3a581c703f160dad", + "hash": "BLAKE3 of the program's OpenQASM 3 text, qasm3", + "qasm3": "OPENQASM 3.0;\ninclude \"stdgates.inc\";\ngate prx(theta, phi) a { rz(-phi) a; rx(theta) a; rz(phi) a; }\nbit[2] c;\nprx(pi/2, -pi/2) $0;\nprx(pi/2, -pi/2) $1;\ncz $0, $1;\nprx(pi/2, pi/2) $1;\nc[0] = measure $0;\nc[1] = measure $1;\n", + "native_gates": 4, + "two_qubit_gates": 1, + "swaps": 0, + "layout": [ + 0, + 1 + ], + "final_layout": [ + 0, + 1 + ], + "checked": "the compiled program's final state equals the circuit's, each logical qubit on the physical qubit it ends on, by the bit-exact simulator here; nothing has been sent", + "qubit_names": { + "0": "QB1", + "1": "QB2" + }, + "placement": { + "chosen": "the compiler's own layout, the fewest swaps: the description does not read as a device target (describe: native_gates lists the device's gates)" + } + }, + "job": { + "id": "prx-0", + "polls": 1 + }, + "ideal": { + "computed": true, + "method": "exact", + "total_variation_distance": 0.0, + "hellinger_fidelity": 1.0, + "sampling_tvd_expected": 0.019947114020071634, + "ideal_outcomes": 2, + "note": "the circuit's exact distribution over its classical bits, by the bit-exact state vector here, against the provider's counts: the total variation distance, the Hellinger fidelity, and the distance this many shots of the exact distribution would leave on average (by the normal approximation); a distance well above that is the device's or the simulator's error, or a program not run as sent" + }, + "cost": { + "free": false, + "estimate": { + "unknown": "the provider gives no estimate" + }, + "charged": null, + "confirmed": true + }, + "energy": { + "unmetered": "the work ran at the provider; this host's meter would read only the wait" + }, + "counts_source": "vendor_counts", + "execution": { + "stated_by": "client", + "sent": { + "fields": [ + "circuits", + "shots" + ], + "settings": {} + }, + "verbatim": false, + "note": "this client sends only circuits and shots: it sets nothing, so every step is the service's default, whatever that is", + "mitigation": "default", + "twirling": "default", + "decoupling": "default", + "remapping": "default", + "optimisation": "default" + }, + "counts": { + "00": 200, + "11": 200 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "engine": { + "name": "wai-quantum", + "version": "0.8.1" + }, + "schema": "wai.quantum.job-result/1", + "planner": { + "format": "wai.quantum.planner/1", + "wanted": "measured", + "wanted_from": "contract", + "named": "provider:lab", + "question": "counts", + "auto": null, + "host": { + "job_bytes": 8589934592, + "providers": [ + "lab" + ] + }, + "routes": [ + { + "route": "method:exact", + "kind": "local", + "method": "exact", + "class": "bit-exact", + "host_dependent": false, + "auto_rank": 20, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector", + "kind": "local", + "method": "statevector", + "class": "exact", + "host_dependent": false, + "auto_rank": 30, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:statevector_single", + "kind": "local", + "method": "statevector_single", + "class": "single", + "host_dependent": true, + "auto_rank": 40, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer", + "kind": "local", + "method": "stabilizer", + "class": "exact", + "host_dependent": false, + "auto_rank": 10, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pauli", + "kind": "local", + "method": "pauli", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:mps", + "kind": "local", + "method": "mps", + "class": "heuristic", + "host_dependent": false, + "auto_rank": 60, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:stabilizer_rank", + "kind": "local", + "method": "stabilizer_rank", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:tensor_network", + "kind": "local", + "method": "tensor_network", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank", + "kind": "local", + "method": "cutrank", + "class": "exact", + "host_dependent": false, + "auto_rank": 50, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:cutrank_single", + "kind": "local", + "method": "cutrank_single", + "class": "single", + "host_dependent": true, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:density_matrix", + "kind": "local", + "method": "density_matrix", + "class": "exact", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:trajectories", + "kind": "local", + "method": "trajectories", + "class": "estimate", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "method:pulse", + "kind": "local", + "method": "pulse", + "class": "bounded", + "host_dependent": false, + "auto_rank": null, + "price": null, + "outcome": "rejected", + "rejected": { + "code": "not_named", + "why": "the job names another route" + } + }, + { + "route": "provider:lab", + "kind": "provider", + "provider": "lab", + "class": "measured", + "host_dependent": true, + "price": { + "money": { + "free": false, + "unknown": "the service states its prices in the person's account, not through this protocol" + }, + "time": { + "seconds": null, + "why": "the provider's estimate states no time" + }, + "memory_bytes": null, + "work": null, + "energy": { + "joules": null, + "why": "no provider states a job's energy before it runs" + }, + "leaves_out": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "cancel", + "charged" + ], + "program": { + "shots": 400, + "native_gates": 4, + "two_qubit_gates": 1, + "swaps": 0 + } + }, + "device": "prx-circuits:test-qc", + "provenance": "silicon", + "outcome": "chosen" + } + ], + "choice": "provider:lab", + "why": "the cheapest of the 1 of 14 routes that meet the contract", + "stable": { + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": [ + "method:exact", + "method:statevector", + "method:stabilizer", + "method:pauli", + "method:mps", + "method:stabilizer_rank", + "method:tensor_network", + "method:cutrank", + "method:density_matrix", + "method:trajectories", + "method:pulse" + ], + "digest": "d603bacb92daa1043db820e5b85f4b2aec8f9e9ec8aff536d0d04019e153074d", + "choice": false + }, + "shadow": { + "route": "method:exact", + "class": "bit-exact", + "request": { + "qasm": "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n", + "shots": 400, + "seed": 4294967301, + "method": "exact" + }, + "budget_seconds": 300.0, + "price": { + "money": { + "free": true + }, + "time": { + "seconds": 4e-8, + "basis": "nominal" + }, + "memory_bytes": 134217920, + "work": 8, + "energy": { + "joules": null, + "why": "this host estimates no job's energy before it runs" + }, + "leaves_out": [] + } + }, + "kept": {} + }, + "shadow": { + "ran": true, + "route": "method:exact", + "accuracy": { + "class": "bit-exact" + }, + "request": { + "qasm": "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n", + "shots": 400, + "seed": 4294967301, + "method": "exact" + }, + "shots": 400, + "counts": { + "11": 211, + "00": 189 + }, + "distinct_outcomes": 2, + "omitted_shots": 0, + "distance": { + "computed": true, + "numerator": 22, + "denominator": 800, + "total_variation": 0.0275, + "hellinger_fidelity": 0.9992431772192786, + "sampling_tvd_bound": 0.039915404643269786 + }, + "elapsed_ms": 0 + }, + "receipt": { + "alg": "ed25519", + "canon": "rfc8785", + "key": "197f6b23e16c8532c6abc838facd5ea789be0c76b2920334039bfa8b3d368d61", + "digest": "eb120bfdd0deddf496a319b69627b745f522e00c4918c6ca2c1781490320b2e6", + "signature": "d6f57c66f6f68d729af292c4602a30b68e9439558e638b8273528e7b94c45222dccf9528135ade9b373663bb33f547cf3e486c166b3a30ba8e45c2ce94c54503" + } + } +} diff --git a/wai/quantum-conformance/receipts/made.lock.json b/wai/quantum-conformance/receipts/made.lock.json index 54e1afcd7..bd83864b5 100644 --- a/wai/quantum-conformance/receipts/made.lock.json +++ b/wai/quantum-conformance/receipts/made.lock.json @@ -1,5 +1,15 @@ { "cli-compile.json": "1afbddc31dd54eb98a28df16b472769b5e6b12915d8cc72eb5d0093cd8c29593", + "cli-contract-any.json": "f94b7119043951dc6b30be599cd3a6b3d34c897f04531b3cd70d0abb145735a1", + "cli-contract-auto.json": "6844a85707cd18e1cf9038cde4ddc0bdee8e9d861d65fd11a6340c69e416ecbf", + "cli-contract-bounded.json": "6a0d2e10c024f4ae8ffc185d800d7fd507dd30b24e0c52b4f5d01f0453298a47", + "cli-contract-fabric-cpu.json": "61ce33ef961b5f2fda544834743484debc8d687f28644fc614b82d930f96932a", + "cli-contract-local.json": "f8c3f3f2c85c85a6ed0c7da3b15e55af884fd8d06c441e13d93a5e72347cf5a7", + "cli-contract-provider-priced.json": "5f6dce9e461a3aa12ec7cf7c4975734b75c23cfecc53636a5d102788fa645cbc", + "cli-contract-pulse.json": "ecad0f4f3100d67d6cffabe320c842c7c7a5f663e923452af54f92eb3157fab0", + "cli-contract-routed-seed.json": "ea670c35884bdc5d03cb53fee8b2db4d5bec46c9c021a2b409c97ee0cb170f32", + "cli-contract-routed.json": "1375789f3936028fb6b7147ee1869e1f7782e86d15c1a58c9808ec017e831b78", + "cli-contract-target.json": "50c16b8f42b3ab6e13a31268a3d6a48c58f17234f9a7aa3b1ae57c34650bc310", "cli-provider-reference-priced.json": "e569e1810da66580c9da4c4fb1185490919d03066f104de8332f99ac214a728b", "cli-provider-reference.json": "ade872d1a9e34a70f9f3928218b64b91ef2df8c21229778d79cd9cbbbb436f0c", "cli-run-mps.json": "9f8fdd7f57566b63e66e979769caae330a32fe01520d909a82f1ecba5c5a6f04", @@ -16,6 +26,7 @@ "scripted-cloud-tasks-processor-probabilities.json": "63f457f817d940d8af7e161b66aeb6b089e46c80a06c8b640b0a8ad3bd4c46cb", "scripted-cloud-tasks-processor.json": "1eb499584183085209fa4597e0f8956826f18cf29d0885e7ad9a1c55a656f66d", "scripted-cloud-tasks-simulator.json": "cc99f5d91138569f7584f913c88293a8581085ef6a38944f7425ad86591252c4", + "scripted-contract-prx-circuits.json": "1ec0c24711183e27e7f83752abf35a2ef53c852313cf65240161dacd58cf1592", "scripted-native-turns-noise.json": "8a6c1bac37f1b6a856d891dbc657d91c252a40eb7a5a09ab0ec9474233425385", "scripted-native-turns.json": "9cc3b887aba07437b2a3ad6e20e7f656853c63bf8c94c21c715efdfddf95ee77", "scripted-prx-circuits.json": "d1c74db10b01a23a7b66d90356a33b8f7afc37efd7c75a5af26fbd87f99cda6b", diff --git a/wai/quantum-conformance/receipts/make.sh b/wai/quantum-conformance/receipts/make.sh index 50c14673b..2a1b1cb5c 100644 --- a/wai/quantum-conformance/receipts/make.sh +++ b/wai/quantum-conformance/receipts/make.sh @@ -33,6 +33,25 @@ printf 'OPENQASM 3.0;\ninclude "stdgates.inc";\nqubit[1] q;\nrx(0.4) q[0];\n' > printf 'OPENQASM 3.0;\ninclude "stdgates.inc";\ninput float theta;\nqubit[1] q;\nbit[1] c;\nrx(theta) q[0];\nc = measure q;\n' > theta.qasm "$B" run bell.qasm --program three.qasm --shots 64 --seed 3 --demo-key --json > "$OUT/cli-set-programs.json" "$B" run theta.qasm --sweep theta=0.25,0.5,1.5 --shots 64 --seed 9 --demo-key --json > "$OUT/cli-set-sweep.json" +# Jobs under a contract (section 8.7): the cheapest exact route here, under a deadline and a +# ceiling; auto's class kept; every route weighed with the person's providers, the free +# simulator chosen by its class and shadowed (and again with a seed whose shadow's wraps at +# 2^53); any class, where a method here and a free provider tie on money and time and the +# method comes first; a provider named and allowed, under a ceiling, confirmed; bounded, where a single- +# precision route does not meet it; the CPU asked for; a device target beside the person's +# providers; and a pulse program. +printf 'OPENQASM 3.0;\ninclude "stdgates.inc";\nqubit[2] q;\nbit[2] c;\nrx(0.3) q[0];\ncx q[0], q[1];\nc = measure q;\n' > rot.qasm +printf 'OPENQASM 3.0;\ndefcalgrammar "openpulse";\ncal {\n extern port d0;\n extern port a0;\n frame q0 = newframe(d0, 5.0e9, 0);\n frame c0 = newframe(a0, 5.0e9, 0);\n}\ndefcal x $0 { play(q0, drag(0.4, 64dt, 16dt, 0.2)); }\ndefcal measure $0 -> bit { return capture_v2(c0, 100dt); }\nbit c;\nx $0;\nc = measure $0;\n' > pulse.qasm +"$B" run bell.qasm --shots 1000 --seed 7 --exactness exact --deadline 60 --max-cost 1:USD --demo-key --json > "$OUT/cli-contract-local.json" +"$B" run three.qasm --shots 500 --seed 3 --deadline 600 --demo-key --json > "$OUT/cli-contract-auto.json" +"$B" run bell.qasm --shots 300 --seed 4 --exactness simulated --allow-providers --demo-key --json > "$OUT/cli-contract-routed.json" +"$B" run bell.qasm --shots 300 --seed 9007199254740990 --exactness simulated --allow-providers --demo-key --json > "$OUT/cli-contract-routed-seed.json" +"$B" run bell.qasm --shots 100 --seed 2 --exactness any --allow-providers --deadline 60 --demo-key --json > "$OUT/cli-contract-any.json" +"$B" run bell.qasm --provider priced --allow-providers --shots 300 --seed 4 --max-cost 1:USD --yes --demo-key --json > "$OUT/cli-contract-provider-priced.json" +"$B" run rot.qasm --shots 100 --seed 2 --exactness bounded --deadline 60 --demo-key --json > "$OUT/cli-contract-bounded.json" +"$B" run bell.qasm --shots 100 --seed 2 --fabric cpu --deadline 60 --demo-key --json > "$OUT/cli-contract-fabric-cpu.json" +"$B" run bell.qasm --shots 50 --seed 2 --target synthetic-line-5 --allow-providers --deadline 60 --demo-key --json > "$OUT/cli-contract-target.json" +"$B" run pulse.qasm --method pulse --shots 50 --seed 2 --exactness bounded --deadline 60 --demo-key --json > "$OUT/cli-contract-pulse.json" "$B" submit bell.qasm --shots 200 --seed 11 --json > "$OUT/service-run.json" "$B" submit bell.qasm --shots 200 -o "Z0 Z1" --json > "$OUT/service-run-stabilizer.json" for f in "$OUT"/cli-*.json "$OUT"/service-*.json; do "$B" verify "$f" > /dev/null || { echo "make.sh: $f does not verify" >&2; exit 1; }; done diff --git a/wai/quantum-conformance/receipts/manifest.json b/wai/quantum-conformance/receipts/manifest.json index 3749608c8..b5cc12fa7 100644 --- a/wai/quantum-conformance/receipts/manifest.json +++ b/wai/quantum-conformance/receipts/manifest.json @@ -7,6 +7,66 @@ "made_by": "made", "what": "the command line: a compile, its certificate and its receipt" }, + { + "file": "jobs/cli-contract-any.json", + "reasons": [], + "made_by": "made", + "what": "the command line under a contract that takes any class, the person's providers allowed: a free method here and a free provider tie on money and on time to the millisecond, and the method here comes first" + }, + { + "file": "jobs/cli-contract-auto.json", + "reasons": [], + "made_by": "made", + "what": "the command line under a contract that names no class: auto's pick kept, held to a deadline" + }, + { + "file": "jobs/cli-contract-bounded.json", + "reasons": [], + "made_by": "made", + "what": "the command line under a contract that wants bounded: a single-precision route does not meet it, and the state vector is chosen" + }, + { + "file": "jobs/cli-contract-fabric-cpu.json", + "reasons": [], + "made_by": "made", + "what": "the command line on the CPU it asks for, under a deadline: each route that runs on an accelerator rejected for it" + }, + { + "file": "jobs/cli-contract-local.json", + "reasons": [], + "made_by": "made", + "what": "the command line under a contract: exact, a deadline and a ceiling, the cheapest route here chosen and its reasoning sealed" + }, + { + "file": "jobs/cli-contract-provider-priced.json", + "reasons": [], + "made_by": "made", + "what": "the command line on a provider it names, allowed by its contract and under a ceiling, confirmed with --yes: the estimate held to the ceiling, the charge to it after, and the shadow" + }, + { + "file": "jobs/cli-contract-pulse.json", + "reasons": [], + "made_by": "made", + "what": "the command line, a pulse program under a contract that wants bounded and a deadline: its one route" + }, + { + "file": "jobs/cli-contract-routed-seed.json", + "reasons": [], + "made_by": "made", + "what": "the same routed job with the seed 2^53 - 2: its shadow's seed, the request's plus 2^32, wraps at 2^53" + }, + { + "file": "jobs/cli-contract-routed.json", + "reasons": [], + "made_by": "made", + "what": "the command line under a contract that allows the person's providers and wants a simulator's counts: the free one chosen, a classical method's counts and their distance beside its own" + }, + { + "file": "jobs/cli-contract-target.json", + "reasons": [], + "made_by": "made", + "what": "the command line on a device target, the person's providers allowed beside it, under a deadline: the target's method is named, and the providers are not" + }, { "file": "jobs/cli-provider-reference-priced.json", "reasons": [], @@ -103,6 +163,12 @@ "made_by": "made", "what": "cloud-tasks on its simulator: simulated" }, + { + "file": "jobs/scripted-contract-prx-circuits.json", + "reasons": [], + "made_by": "made", + "what": "prx-circuits named under a contract that wants a device's counts, confirmed: its counts, the planner's reasoning, and a classical method's counts and their distance beside them" + }, { "file": "jobs/scripted-native-turns-noise.json", "reasons": [], @@ -1162,6 +1228,928 @@ "reasons": [], "made_by": "crafted", "what": "a class a verifier does not know: not a reason, since a later version may add one" + }, + { + "file": "jobs/crafted-contract-form-member.json", + "reasons": [ + "contract_form" + ], + "made_by": "crafted", + "what": "a member no contract has: read as absent, a requirement would drop in silence" + }, + { + "file": "jobs/crafted-contract-form-exactness.json", + "reasons": [ + "contract_form" + ], + "made_by": "crafted", + "what": "an exactness that is no class" + }, + { + "file": "jobs/crafted-contract-form-cost.json", + "reasons": [ + "contract_form" + ], + "made_by": "crafted", + "what": "a ceiling's amount that is not in decimals" + }, + { + "file": "jobs/crafted-contract-form-cost-long.json", + "reasons": [ + "contract_form" + ], + "made_by": "crafted", + "what": "a ceiling's amount of 65 characters: at most 64" + }, + { + "file": "jobs/crafted-contract-planner-missing.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a contract job sealed without its reasoning" + }, + { + "file": "jobs/crafted-contract-planner-format.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a reasoning of another format" + }, + { + "file": "jobs/crafted-contract-planner-wanted.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a class wanted that is not the contract's" + }, + { + "file": "jobs/crafted-contract-planner-wanted-from.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a class said to be the contract's, where the contract names none and the job keeps auto's" + }, + { + "file": "jobs/crafted-contract-planner-on-plain.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a job with no contract that carries a reasoning" + }, + { + "file": "jobs/crafted-contract-shadow-on-plain.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a job with no contract that carries a shadow" + }, + { + "file": "jobs/crafted-contract-route-claimed.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "a heuristic route said to meet exact" + }, + { + "file": "jobs/crafted-contract-route-code.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "a route rejected for a reason the rules do not give it" + }, + { + "file": "jobs/crafted-contract-choice-dearer.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "another route that meets the contract chosen and run, where the rule picks the cheaper" + }, + { + "file": "jobs/crafted-contract-choice-not-run.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "the route chosen is not what ran" + }, + { + "file": "jobs/crafted-contract-stable-digest.json", + "reasons": [ + "planner_stable" + ], + "made_by": "crafted", + "what": "a digest that is not what the routes' prices give" + }, + { + "file": "jobs/crafted-contract-stable-choice.json", + "reasons": [ + "planner_stable" + ], + "made_by": "crafted", + "what": "a choice said to depend on the host, where it depends on nothing of it" + }, + { + "file": "jobs/crafted-contract-route-price-work.json", + "reasons": [ + "planner_stable" + ], + "made_by": "crafted", + "what": "a price changed that the digest covers and the order does not: the rule still picks the route" + }, + { + "file": "jobs/crafted-contract-route-price-memory.json", + "reasons": [ + "planner_choice", + "planner_stable" + ], + "made_by": "crafted", + "what": "a price changed that the digest covers and the order reads: another route that meets the contract now comes first" + }, + { + "file": "jobs/crafted-contract-kept-false.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "a deadline said missed that was kept" + }, + { + "file": "jobs/crafted-contract-kept-dropped.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "a ceiling the contract gives, and kept does not state" + }, + { + "file": "jobs/crafted-contract-kept-missed-stated.json", + "reasons": [], + "made_by": "crafted", + "what": "a deadline missed and said so: an answer all the same, and valid" + }, + { + "file": "jobs/crafted-contract-class-short.json", + "reasons": [ + "contract_class" + ], + "made_by": "crafted", + "what": "a result whose class does not meet the class wanted" + }, + { + "file": "jobs/crafted-contract-shadow-on-local.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a local route's result that carries a shadow" + }, + { + "file": "jobs/crafted-contract-shadow-missing.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a provider's answer without its shadow" + }, + { + "file": "jobs/crafted-contract-shadow-plan-missing.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a provider's answer whose reasoning planned no shadow" + }, + { + "file": "jobs/crafted-contract-shadow-numerator.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a distance that is not what the two lists of counts give" + }, + { + "file": "jobs/crafted-contract-shadow-not-computed.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a distance not computed, with every shot listed on both sides" + }, + { + "file": "jobs/crafted-contract-shadow-seed.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow sampled on the job's own stream, not one of its own" + }, + { + "file": "jobs/crafted-contract-shadow-said-none.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow said not to have run, where its plan had a route" + }, + { + "file": "jobs/crafted-contract-shadow-omitted-spelt.json", + "reasons": [], + "made_by": "crafted", + "what": "a shadow's omitted_shots of 0 written as 0.0: 0 by value, and valid" + }, + { + "file": "jobs/crafted-contract-route-provider-claimed.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "a provider that costs money, with no ceiling to hold it to, said to meet the contract" + }, + { + "file": "jobs/crafted-contract-provider-not-chosen.json", + "reasons": [ + "planner_choice", + "request_provider" + ], + "made_by": "crafted", + "what": "an answer from a provider the planner did not choose" + }, + { + "file": "jobs/crafted-contract-providers-not-allowed.json", + "reasons": [ + "planner_choice", + "planner_route", + "request_provider" + ], + "made_by": "crafted", + "what": "a provider's answer to a contract that does not allow one" + }, + { + "file": "jobs/crafted-contract-at-least-false.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "at_least given and not true" + }, + { + "file": "jobs/crafted-contract-at-least-claimed.json", + "reasons": [ + "planner_choice", + "planner_route" + ], + "made_by": "crafted", + "what": "a cost that is the least it can come to, under the ceiling, said to meet it" + }, + { + "file": "jobs/crafted-contract-charged-over.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "charged past the ceiling, and kept said to hold" + }, + { + "file": "jobs/crafted-contract-charged-over-stated.json", + "reasons": [], + "made_by": "crafted", + "what": "charged past the ceiling, and said so: valid" + }, + { + "file": "jobs/crafted-contract-kept-charged-other.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "kept stating a charge that is not the result's: within the ceiling, and not what was charged" + }, + { + "file": "jobs/crafted-contract-kept-member-extra.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "a member of kept that its table does not give" + }, + { + "file": "jobs/crafted-contract-kept-elapsed-other.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "a method's time in kept that is not the run's own elapsed_ms, within the deadline all the same" + }, + { + "file": "jobs/crafted-contract-auto-other.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "auto said to pick a route the ranks do not" + }, + { + "file": "jobs/crafted-contract-auto-rank-lowered.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a route's rank in auto's order lowered, so that auto would pick it" + }, + { + "file": "jobs/crafted-contract-auto-rank-other.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a rank that is not the method's, on a route that does not win by it" + }, + { + "file": "jobs/crafted-contract-auto-rank-missing.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a local route without its rank in auto's order" + }, + { + "file": "jobs/crafted-contract-question-other.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a question the request does not ask" + }, + { + "file": "jobs/crafted-contract-named-other.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a provider the request names, said to be named by nothing" + }, + { + "file": "jobs/crafted-contract-provider-named-not-allowed.json", + "reasons": [ + "contract_provider", + "planner_choice", + "planner_route" + ], + "made_by": "crafted", + "what": "a provider named under a contract that does not allow one: never is the default" + }, + { + "file": "jobs/crafted-contract-named-approximate.json", + "reasons": [], + "made_by": "crafted", + "what": "a provider named, its simulator stated approximate, under a contract that names no class: it keeps the named route's class, and the rule against an approximate simulator holds only a class the contract names" + }, + { + "file": "jobs/crafted-contract-approximate-rejected.json", + "reasons": [], + "made_by": "crafted", + "what": "a simulator stated approximate, where the contract wants simulated: rejected for its class, before its cost is weighed" + }, + { + "file": "jobs/crafted-contract-price-seconds-past.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a time past 10^12 seconds, which a host states as unknown" + }, + { + "file": "jobs/crafted-contract-price-amount-long.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "an amount of 65 characters, which a host states as unknown" + }, + { + "file": "jobs/crafted-contract-local-money.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a method here priced in money: a local route is free" + }, + { + "file": "jobs/crafted-contract-memory-at-cap.json", + "reasons": [ + "planner_stable" + ], + "made_by": "crafted", + "what": "a route that needs exactly the job's memory meets it; the digest covers memory, and is not the routes' now" + }, + { + "file": "jobs/crafted-contract-deadline-unknown.json", + "reasons": [ + "planner_stable" + ], + "made_by": "crafted", + "what": "a route whose time is unknown under a deadline, rejected for it; the digest covers the time, and is not the routes' now" + }, + { + "file": "jobs/crafted-contract-currency-other.json", + "reasons": [ + "planner_choice", + "planner_kept", + "planner_route" + ], + "made_by": "crafted", + "what": "a ceiling in another currency than the estimate's: no route meets it, and kept states another ceiling" + }, + { + "file": "jobs/crafted-contract-energy-at-ceiling.json", + "reasons": [], + "made_by": "crafted", + "what": "an energy ceiling met exactly by a figure sealed after the run, every route watched: kept, and the choice depends on the host" + }, + { + "file": "jobs/crafted-contract-energy-stable-claimed.json", + "reasons": [ + "planner_stable" + ], + "made_by": "crafted", + "what": "the same, the choice said to depend on nothing of the host" + }, + { + "file": "jobs/crafted-contract-energy-unwatched.json", + "reasons": [], + "made_by": "crafted", + "what": "a route nothing can read while it runs, under a ceiling: refused, though its estimate is under it" + }, + { + "file": "jobs/crafted-contract-energy-unwatched-claimed.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "a route nothing can stop, said to meet a ceiling" + }, + { + "file": "jobs/crafted-contract-energy-over-estimate.json", + "reasons": [], + "made_by": "crafted", + "what": "an estimate clearly past the ceiling refuses a watched route" + }, + { + "file": "jobs/crafted-contract-energy-estimate-at-ceiling.json", + "reasons": [], + "made_by": "crafted", + "what": "an estimate exactly at the ceiling is not past it, and refuses nothing" + }, + { + "file": "jobs/crafted-contract-energy-watch-form.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a watch that is no sentence" + }, + { + "file": "jobs/crafted-contract-stopped.json", + "reasons": [], + "made_by": "crafted", + "what": "a run stopped at its ceiling by a live reading: no answer, and a receipt that says so" + }, + { + "file": "jobs/crafted-contract-stopped-kept-claimed.json", + "reasons": [ + "planner_kept" + ], + "made_by": "crafted", + "what": "a stopped run said to have kept its ceiling" + }, + { + "file": "jobs/crafted-contract-stopped-under.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a run said stopped under its ceiling" + }, + { + "file": "jobs/crafted-contract-stopped-with-counts.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stopped run that gives an answer" + }, + { + "file": "jobs/crafted-contract-stopped-whole-below.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stopped run whose whole figure is less than what stopped it" + }, + { + "file": "jobs/crafted-contract-stopped-whole-above.json", + "reasons": [], + "made_by": "crafted", + "what": "a stopped run whose whole figure is a little past what stopped it" + }, + { + "file": "jobs/crafted-contract-stopped-elapsed-fraction.json", + "reasons": [ + "planner_kept", + "stopped" + ], + "made_by": "crafted", + "what": "a stop at a time that is no whole number, the result's the same (a deadline's kept time is whole too)" + }, + { + "file": "jobs/crafted-contract-stopped-elapsed-other.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stop at another time than the result's" + }, + { + "file": "jobs/crafted-contract-stopped-with-verdict.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stopped run that gives a verdict, an answer by another name" + }, + { + "file": "jobs/crafted-contract-stopped-with-outputs.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stopped run that gives outputs" + }, + { + "file": "jobs/crafted-contract-stopped-other-ceiling.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stop at a ceiling the contract does not give" + }, + { + "file": "jobs/crafted-contract-stopped-at-ceiling.json", + "reasons": [], + "made_by": "crafted", + "what": "a reading exactly at the ceiling stops a run" + }, + { + "file": "jobs/crafted-contract-stopped-class.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stopped run that claims a class" + }, + { + "file": "jobs/crafted-contract-stopped-on-provider.json", + "reasons": [ + "contract_form", + "counts", + "planner_choice", + "provider_class", + "request_provider", + "request_shots", + "stopped" + ], + "made_by": "crafted", + "what": "a stop on a provider's run, which nothing here reads: and a local job's request and route, which no provider's result can have, in the earlier form" + }, + { + "file": "jobs/crafted-contract-stopped-read-form.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stop that does not say what read it" + }, + { + "file": "jobs/crafted-contract-stopped-elapsed-form.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stop at a time that is no whole number" + }, + { + "file": "jobs/crafted-contract-stopped-extra-member.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stop with a member its form does not have" + }, + { + "file": "jobs/crafted-contract-stopped-at-other.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a stop at something other than the energy ceiling" + }, + { + "file": "jobs/crafted-contract-energy-watch-both.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a route said both to be read and to have no reading" + }, + { + "file": "jobs/crafted-contract-stopped-on-plain.json", + "reasons": [ + "stopped" + ], + "made_by": "crafted", + "what": "a job with no contract said to have been stopped" + }, + { + "file": "jobs/crafted-contract-route-class-gpu.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "the GPU's single precision stated exact: a class its method does not have" + }, + { + "file": "jobs/crafted-contract-route-class-by-job.json", + "reasons": [ + "planner_route", + "planner_stable" + ], + "made_by": "crafted", + "what": "the stabilizer stated estimate, on a job with no noise and no target" + }, + { + "file": "jobs/crafted-contract-route-host-dependent.json", + "reasons": [ + "planner_route", + "planner_stable" + ], + "made_by": "crafted", + "what": "a built-in on no GPU said to depend on the host, which takes it out of the digest" + }, + { + "file": "jobs/crafted-contract-route-provider-host-independent.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "a provider's route said not to depend on the host" + }, + { + "file": "jobs/crafted-contract-result-class-foreign.json", + "reasons": [ + "contract_class" + ], + "made_by": "crafted", + "what": "the stabilizer's result stated bit-exact: it meets what is wanted, and its method has no such class" + }, + { + "file": "jobs/crafted-contract-price-memory-null.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a method's memory stated null, which passes the memory rule and wins its tie" + }, + { + "file": "jobs/crafted-contract-price-provider-memory.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "a provider's route stating a memory" + }, + { + "file": "jobs/crafted-contract-host-providers-other.json", + "reasons": [ + "planner_form" + ], + "made_by": "crafted", + "what": "host.providers that are not the provider routes" + }, + { + "file": "jobs/crafted-contract-shadow-route-missing.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow that names no route" + }, + { + "file": "jobs/crafted-contract-shadow-plan-route-missing.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow planned with no route, where null would say why" + }, + { + "file": "jobs/crafted-contract-shadow-plan-route-absent.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a plan with neither a route nor null, and a shadow said not to have run" + }, + { + "file": "jobs/crafted-contract-shadow-route-provider.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a provider as its own shadow" + }, + { + "file": "jobs/crafted-contract-shadow-request-extra.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow run under a noise model the job never asked for, on both sides" + }, + { + "file": "jobs/crafted-contract-shadow-plan-code.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow planned with a code no plan has" + }, + { + "file": "jobs/crafted-contract-shadow-plan-class.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow planned at a class its route is not listed with" + }, + { + "file": "jobs/crafted-contract-shadow-plan-budget.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a budget that is not what the contract leaves" + }, + { + "file": "jobs/crafted-contract-shadow-plan-price-over.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow planned at a time past its budget" + }, + { + "file": "jobs/crafted-contract-shadow-count-fraction.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow's counts that are not whole, summing to the shots all the same" + }, + { + "file": "jobs/crafted-contract-shadow-count-sum.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow's counts that sum to more than its shots" + }, + { + "file": "jobs/crafted-contract-shadow-count-short.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shot said omitted beside counts that are all the shots: they sum to one more, and the distance, not computed, is no help" + }, + { + "file": "jobs/crafted-contract-shadow-distinct.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow that says more outcomes than it lists, none omitted" + }, + { + "file": "jobs/crafted-contract-shadow-class-foreign.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow run by mps stated bit-exact: it meets its plan, and mps has no such class" + }, + { + "file": "jobs/crafted-contract-shadow-bound-other.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a bound on the distance the shots alone leave that is not what the counts give" + }, + { + "file": "jobs/crafted-contract-cost-route-free-run-paid.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "a run sealed at 50 USD on a route the reasoning calls free: not the route chosen" + }, + { + "file": "jobs/crafted-contract-cost-route-paid-run-free.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "a paid route chosen, its run sealed as free and unconfirmed" + }, + { + "file": "jobs/crafted-contract-cost-amount-other.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "a run sealed at another estimate than its route's" + }, + { + "file": "jobs/crafted-contract-cost-unknown-run-free.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "a route whose cost is not known, its run sealed as free and unconfirmed" + }, + { + "file": "jobs/crafted-contract-cost-at-least-dropped.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "a route's estimate the least it can come to, its run's estimate sealed as the whole" + }, + { + "file": "jobs/crafted-contract-route-device-other.json", + "reasons": [ + "planner_choice" + ], + "made_by": "crafted", + "what": "the route chosen names another device than the one that ran" + }, + { + "file": "jobs/crafted-contract-route-provenance-class.json", + "reasons": [ + "planner_route" + ], + "made_by": "crafted", + "what": "a provider's route whose class is not its provenance's" + }, + { + "file": "jobs/crafted-contract-shadow-width-other.json", + "reasons": [ + "shadow" + ], + "made_by": "crafted", + "what": "a shadow whose outcomes are wider than the job's, its distance what they give" + }, + { + "file": "jobs/crafted-contract-route-mps-exact.json", + "reasons": [ + "planner_route", + "planner_stable" + ], + "made_by": "crafted", + "what": "the matrix product state's route stated exact, which a route of it never is" + }, + { + "file": "jobs/crafted-contract-route-registered-host-independent.json", + "reasons": [ + "planner_route", + "planner_stable" + ], + "made_by": "crafted", + "what": "a method the host registered, stated to depend on nothing of the host" + }, + { + "file": "jobs/crafted-contract-shadow-said-failed.json", + "reasons": [], + "made_by": "crafted", + "what": "a shadow planned and said to have failed: valid to read, and run again by --recheck" } ] } diff --git a/wai/quantum-conformance/tools/receipt_differential.py b/wai/quantum-conformance/tools/receipt_differential.py index cb46ebd0e..cbf73c8e8 100644 --- a/wai/quantum-conformance/tools/receipt_differential.py +++ b/wai/quantum-conformance/tools/receipt_differential.py @@ -85,10 +85,30 @@ def run_lines(cmd, path, n): return verdicts(p.stdout, n) +def _same_number(v): + """A stated value with each number past 2^53 read as the double both verifiers + hold it as, so that one writing it whole and the other as a double agree.""" + if isinstance(v, bool) or v is None: + return v + if isinstance(v, int): + return float(v) if abs(v) > 2 ** 53 else v + if isinstance(v, dict): + return dict((k, _same_number(x)) for k, x in v.items()) + if isinstance(v, list): + return [_same_number(x) for x in v] + return v + + def said(v): - """What a verdict says that both verifiers must agree on.""" + """What a verdict says that both verifiers must agree on: its reasons, its key + and form, what it reads of a provider's result, and of a job under a contract + the choice, the class wanted and the class given, what was kept, the stable + choice, and the shadow (whether it ran and its total variation).""" p = v.get("provider") or {} - return (tuple(sorted(v.get("reasons", []))), v.get("key"), v.get("form"), p.get("form"), p.get("read_as"), p.get("counts_source")) + c = v.get("planner") or {} + return (tuple(sorted(v.get("reasons", []))), v.get("key"), v.get("form"), p.get("form"), p.get("read_as"), p.get("counts_source"), + c.get("choice"), c.get("wanted"), c.get("class"), c.get("stable_choice"), _same_number(c.get("kept")), c.get("shadow_ran"), + _same_number(c.get("shadow_total_variation"))) # ----------------------------------------------------------------- one change at a time diff --git a/wai/quantum-conformance/tools/receipt_verify.py b/wai/quantum-conformance/tools/receipt_verify.py index e6810d532..9d5d40265 100644 --- a/wai/quantum-conformance/tools/receipt_verify.py +++ b/wai/quantum-conformance/tools/receipt_verify.py @@ -18,12 +18,14 @@ with "key" the receipt's key hex when the receipt is of its form (else null) and "provider": {"form": "stated"|"earlier", "class", "read_as", "counts_source", "execution"}. The exit status is 0 only when every verdict is valid. -The reasons are exactly §8.4's and §8.6's: +The reasons are exactly §8.4's, §8.6's and §8.7's: unreadable, not_a_job, no_receipt (each reported alone); receipt_form, digest_mismatch, bad_key, bad_signature; inexact_number; provider_class, request_provider, request_shots, counts (every provider result); provider_members, counts_source, execution, compiled_program, cost_confirmation (the stated form); - set_items, set_item, set_root (a set, §8.6). + set_items, set_item, set_root (a set, section 8.6); + contract_form, planner_form, planner_route, planner_choice, planner_stable, + planner_kept, contract_class, shadow, stopped (a job under a contract, section 8.7). --plant NAME exists only to prove that a differential against another verifier can fail: each plant breaks one rule on purpose, and a verifier run with one is @@ -38,12 +40,16 @@ wrong by design. NAME is one of: no-canonical-spelling refuse an inexact whole number even in its canonical spelling set-seal-only check a set's seal, and nothing of its items or its root names-layout-only check compiled.qubit_names against the layouts only, not qasm3 + route-unchecked take each route's stated outcome as it stands (section 8.7) + choice-unchecked take the planner's choice as it stands (section 8.7) + distance-unchecked take a shadow's stated distance as it stands (section 8.7) Without --plant the verifier is exactly §8's. Its reader's questions of the text, gap by gap, are what §8 now says: where §8 left a choice, it was settled in the text, and this file follows the text. """ +import fractions import hashlib import json import math @@ -54,7 +60,7 @@ import time PLANTS_KNOWN = ("lenient-key", "no-alg", "last-duplicate", "no-inexact", "measured-simulator", "whole-cap", "lax-small-order-r", "no-canonical-spelling", "set-seal-only", - "names-layout-only") + "names-layout-only", "route-unchecked", "choice-unchecked", "distance-unchecked") PLANTS = set() MAX_DEPTH = 127 # §8.2: nesting deeper than 127 is unreadable @@ -995,7 +1001,12 @@ def check_provider(request, result, reasons): stated = "counts_source" in result or "execution" in result check_class(result, True, stated, reasons) # §8.4 request_provider: provider.name a string equal to the request's provider. + # §8.4, §8.7: or, when the request gives none and its contract allows a provider, + # the one its planner chose. name, asked = _member(result, "provider", "name"), request.get("provider") + if asked is None and _member(request, "contract", "providers") == "allowed": + choice = _member(result, "planner", "choice") + asked = choice[len("provider:"):] if isinstance(choice, str) and choice.startswith("provider:") else None if not (isinstance(name, str) and isinstance(asked, str) and name == asked): reasons.add("request_provider") # §8.4 request_shots: the request's shots, 1024 when it gives none or null. @@ -1034,6 +1045,792 @@ def provider_statement(result): } +# ================================================== 6b. a job under a contract (§8.7) + +CONTRACT_MEMBERS = ("exactness", "max_cost", "deadline_seconds", "max_joules", "providers") +MEETS = { + "bit-exact": ("bit-exact",), + "exact": ("bit-exact", "exact"), + "single": ("bit-exact", "exact", "single"), + "bounded": ("bit-exact", "exact", "bounded"), + "estimate": ("bit-exact", "exact", "bounded", "estimate"), + "heuristic": ("bit-exact", "exact", "single", "bounded", "estimate", "heuristic"), + "measured": ("measured",), + "simulated": ("simulated",), +} +CLASSES_WANTED = tuple(MEETS) + ("any",) +LADDER = ("bit-exact", "exact", "single", "bounded", "estimate", "heuristic") +LEAVES_OUT = ("time", "amount", "energy", "mitigation", "decoder", "charged", "cancel") +QUESTIONS = ("noise", "counts", "expectations", "amplitudes") +_DECIMAL = re.compile(r"[0-9]+(?:\.[0-9]+)?") +_GPU_METHODS = ("method:statevector_single", "method:cutrank_single") +MAX_SECONDS = 1e12 # §8.7: the most seconds a price may state +MAX_AMOUNT = 64 # §8.7: the most characters an amount may have +# §8.7: each built-in method's rank in auto's order, by question (noise, counts, +# expectations, amplitudes); None where auto does not try it for that question. +AUTO_RANKS = { + "exact": (None, 20, 20, 10), + "statevector": (None, 30, 30, 20), + "statevector_single": (None, 40, 40, 30), + "stabilizer": (20, 10, 10, None), + "pauli": (None, None, 60, None), + "mps": (None, 60, 70, 70), + "stabilizer_rank": (None, None, 50, 50), + "tensor_network": (None, None, None, 60), + "cutrank": (None, 50, None, 40), + "cutrank_single": (None, None, None, None), + "density_matrix": (10, None, None, None), + "trajectories": (30, None, None, None), + "pulse": (None, None, None, None), +} + + +# §8.7: the classes each built-in method can have; which of two, on a job, by _route_class. +METHOD_CLASSES = { + "exact": ("bit-exact",), + "statevector": ("exact",), + "statevector_single": ("single",), + "stabilizer": ("exact", "estimate"), + "pauli": ("bounded",), + "mps": ("exact", "heuristic"), + "stabilizer_rank": ("exact", "estimate"), + "tensor_network": ("exact",), + "cutrank": ("exact", "single"), + "cutrank_single": ("single",), + "density_matrix": ("exact",), + "trajectories": ("estimate",), + "pulse": ("bounded",), +} +_GPU_NAMES = ("statevector_single", "cutrank_single") + + +def meets(wanted, got): + """§8.7's table. `any` takes every class; a class nobody knows meets nothing else.""" + return wanted == "any" or (wanted in MEETS and got in MEETS[wanted]) + + +def _is_decimal(s): + """§8.7: digits, optionally '.' and digits, at most 64 characters.""" + return isinstance(s, str) and len(s) <= MAX_AMOUNT and _DECIMAL.fullmatch(s) is not None + + +def _value_of(v): + return v.value if isinstance(v, Num) else None + + +def _same_keys(v, keys): + return isinstance(v, dict) and set(v) == set(keys) + + +def read_contract(c): + """§8.7: the contract as (exactness, max_cost, deadline, joules, providers), or None + when it is not of its form. Null is absent.""" + if not isinstance(c, dict) or any(k not in CONTRACT_MEMBERS for k in c): + return None + exactness = c.get("exactness") + if exactness is not None and exactness not in CLASSES_WANTED: + return None + cost = c.get("max_cost") + if cost is not None: + if not (isinstance(cost, dict) and len(cost) == 2 and _is_decimal(cost.get("amount")) + and isinstance(cost.get("currency"), str) and cost["currency"]): + return None + for k in ("deadline_seconds", "max_joules"): + v = c.get(k) + if v is not None and not (isinstance(v, Num) and v.value > 0): + return None + providers = c.get("providers") + if providers is not None and providers not in ("never", "allowed"): + return None + return {"exactness": exactness, "max_cost": cost, + "deadline": c["deadline_seconds"].value if c.get("deadline_seconds") is not None else None, + "joules": c["max_joules"].value if c.get("max_joules") is not None else None, + "providers": providers} + + +def _seconds_ok(v): + return isinstance(v, Num) and 0 <= v.value <= MAX_SECONDS + + +def _price_form(p, local): + """§8.7: a price. A local route's money is free; seconds and amounts are bounded.""" + if not isinstance(p, dict): + return False + m = p.get("money") + if not isinstance(m, dict): + return False + if m.get("free") is False: + if local or not (isinstance(m.get("unknown"), str) or (isinstance(m.get("amount"), str) and isinstance(m.get("currency"), str))): + return False + elif m.get("free") is not True: + return False + if "at_least" in m and m["at_least"] is not True: + return False + if "amount" in m and not (isinstance(m["amount"], str) and len(m["amount"]) <= MAX_AMOUNT): + return False + t = p.get("time") + if not isinstance(t, dict) or not (t.get("seconds") is None or _seconds_ok(t["seconds"])): + return False + e = p.get("energy") + if not isinstance(e, dict) or not (e.get("joules") is None or isinstance(e["joules"], Num)): + return False + if any(k in e and not isinstance(e[k], str) for k in ("watch", "unwatched")) or ("watch" in e and "unwatched" in e): + return False + left = p.get("leaves_out") + if not isinstance(left, list) or any(w not in LEAVES_OUT for w in left): + return False + for k in ("memory_bytes", "work"): + # A method's are whole numbers, and a provider's null: it states neither. + if k not in p or not ((_whole(p[k]) and p[k].value >= 0) if local else p[k] is None): + return False + return True + + +def _route_form(r): + if not isinstance(r, dict): + return False + name, kind = r.get("route"), r.get("kind") + if not isinstance(name, str): + return False + local = name.startswith("method:") and len(name) > 7 and kind == "local" + if not (local or (name.startswith("provider:") and len(name) > 9 and kind == "provider")): + return False + outcome = r.get("outcome") + if outcome in ("chosen", "met"): + if "rejected" in r: + return False + elif outcome == "rejected": + rej = r.get("rejected") + if not (isinstance(rej, dict) and isinstance(rej.get("code"), str) and isinstance(rej.get("why"), str)): + return False + else: + return False + if "price" not in r: + return False + if r["price"] is not None and not _price_form(r["price"], local): + return False + if local: + if "auto_rank" not in r or not (r["auto_rank"] is None or (_whole(r["auto_rank"]) and r["auto_rank"].value >= 0)): + return False + return isinstance(r.get("class"), str) and isinstance(r.get("host_dependent"), bool) + + +def _class_of_method(method, cls): + """§8.7: whether cls is one the built-in method has; any class of another.""" + return method not in METHOD_CLASSES or cls in METHOD_CLASSES[method] + + +def _states_itself(r, request): + """§8.7: a built-in method has the class its table gives it on this request, and + depends on the host only when it runs on a GPU; a provider's route depends on it.""" + name = r["route"] + cls = r["class"] + if not name.startswith("method:"): + # A provider's route has the class its provenance gives. + given = read_class(r.get("provenance")) + return r["host_dependent"] is True and (given is None or cls == given) + m = name[len("method:"):] + if m not in METHOD_CLASSES: + return r["host_dependent"] is True # a method the host registered is its own code + options = request.get("options") + given = lambda k: isinstance(options, dict) and options.get(k) is not None + if m == "stabilizer": + want = "estimate" if request.get("noise") is not None or request.get("target") is not None else "exact" + if cls != want: + return False + if m == "stabilizer_rank" and cls != ("estimate" if given("terms") or given("epsilon") else "exact"): + return False + # Every other method but cut-rank (whose plan says which table fits) has the one + # class its table gives: the first each class it declares meets. + if m not in ("stabilizer", "stabilizer_rank", "cutrank"): + declared = METHOD_CLASSES[m] + worst = declared[0] if len(declared) == 1 else next((c for c in LADDER if all(meets(c, d) for d in declared)), None) + if cls != worst: + return False + return cls in METHOD_CLASSES[m] and r["host_dependent"] is (m in _GPU_NAMES) + + +def _ran_as_routed(routes, choice, result): + """§8.7: the route chosen is what ran; for a provider's, the result's provider is the + device and provenance it names, where it names them, and the result's cost is its money.""" + r = next((x for x in routes if x["route"] == choice), None) + if r is None or r["kind"] != "provider": + return True + money = _member(r, "price", "money") + cost = result.get("cost") + provider = result.get("provider") + if not (isinstance(money, dict) and isinstance(cost, dict) and isinstance(provider, dict)): + return False + estimate = cost.get("estimate") if isinstance(cost.get("estimate"), dict) else {} + return (all(k not in r or _alike(r[k], provider.get(k)) for k in ("device", "provenance")) + and _alike(cost.get("free"), money.get("free")) + and all(_alike(estimate.get(k), money.get(k)) for k in ("amount", "currency", "unit", "at_least"))) + + +def _alike(a, b): + """§8.7: two members alike: numbers by value (7 and 7.0, -0 and 0), a boolean only + to a boolean, and null as an absent member.""" + if isinstance(a, Num) or isinstance(b, Num): + return isinstance(a, Num) and isinstance(b, Num) and float(a.value) == float(b.value) + if isinstance(a, bool) or isinstance(b, bool): + return isinstance(a, bool) and isinstance(b, bool) and a == b + # Lists and objects member by member, by the same rule. + if isinstance(a, list) or isinstance(b, list): + return isinstance(a, list) and isinstance(b, list) and len(a) == len(b) and all(_alike(x, y) for x, y in zip(a, b)) + if isinstance(a, dict) or isinstance(b, dict): + return isinstance(a, dict) and isinstance(b, dict) and all(_alike(a.get(k), b.get(k)) for k in set(a) | set(b)) + return a == b + + +def _planner_form(p): + if not isinstance(p, dict) or p.get("format") != "wai.quantum.planner/1": + return False + if not (p.get("wanted") is None or isinstance(p["wanted"], str)): + return False + if "wanted_from" not in p: + return False + if p["wanted_from"] is None: + if p.get("wanted") is not None: + return False + elif p["wanted_from"] not in ("contract", "named", "auto"): + return False + routes = p.get("routes") + if not isinstance(routes, list) or not routes or not all(_route_form(r) for r in routes): + return False + names = [r["route"] for r in routes] + if len(set(names)) != len(names): + return False + for k in ("named", "auto"): + if not (p.get(k) is None or p[k] in names): + return False + if p.get("question") not in QUESTIONS or p.get("choice") not in names: + return False + host = p.get("host") + if not isinstance(host, dict) or not (_whole(host.get("job_bytes")) and host["job_bytes"].value >= 0): + return False + providers = host.get("providers") + if not isinstance(providers, list) or not all(isinstance(x, str) for x in providers): + return False + return isinstance(p.get("why"), str) and isinstance(p.get("stable"), dict) and isinstance(p.get("kept"), dict) + + +def _request_names(request): + """§8.7: provider: for the provider a request names, else method: for a + method other than auto, else None.""" + provider = request.get("provider") + if isinstance(provider, str): + return "provider:" + provider + m = request.get("method") + if isinstance(m, str) and m != "auto": + return "method:" + m + return None + + +def _question(request): + """§8.7: the question a job asks, from its request alone.""" + def listed(k): + v = request.get(k) + return isinstance(v, list) and len(v) > 0 + observables, amplitudes = listed("observables"), listed("amplitudes") + shots = request.get("shots") + if isinstance(shots, Num) and shots.literal_whole() and not shots.text.startswith("-") and int(shots.text) <= 2 ** 64 - 1: + shots = int(shots.text) + else: + shots = 1024 if not observables and not amplitudes else 0 + if request.get("noise") is not None: + return "noise" + if shots > 0: + return "counts" + if observables and not amplitudes: + return "expectations" + return "amplitudes" + + +def _fabric(request): + f = request.get("fabric") + if f is None or f == "auto": + return "free" + return "cpu" if f == "cpu" else "placed" + + +def _auto(routes, request, named): + """§8.7: the route auto picks, from the routes.""" + if named is not None: + return None + if _fabric(request) == "placed": + for r in routes: + if r["route"] == "method:statevector" and r["kind"] == "local" and r["price"] is not None: + return "method:statevector" + return None + best = None + for i, r in enumerate(routes): + if r["kind"] == "local" and r["price"] is not None and r.get("auto_rank") is not None: + key = (r["auto_rank"].value, i) + if best is None or key < best[0]: + best = (key, r["route"]) + return best[1] if best else None + + +def _gate(r, contract, request, named, wanted, from_contract, job_bytes): + """§8.7's rules, in order: the first that applies, or None.""" + name, price = r["route"], r["price"] + is_provider = name.startswith("provider:") + # 1 + if named is not None and name != named: + return "not_named" + # 2 + if named is None: + fabric = _fabric(request) + if fabric == "cpu" and name in _GPU_METHODS: + return "fabric" + if fabric == "placed" and name != "method:statevector": + return "fabric" + cls = r["class"] + # 3 + if cls == "unknown" and price is None: + return "cannot" + # 4 + if wanted is not None: + if not meets(wanted, cls) or (from_contract and wanted == "simulated" and r.get("approximate") is True): + return "class" + elif is_provider: + return "class" + # 5 + if price is None: + return "cannot" + # 6 + memory = _value_of(price["memory_bytes"]) + if memory is not None and memory > job_bytes: + return "memory" + # 7 + if is_provider and contract["providers"] != "allowed": + return "providers" + # 8 + if contract["deadline"] is not None: + seconds = _value_of(price["time"].get("seconds")) + if seconds is None: + return "deadline_unknown" + if seconds > contract["deadline"]: + return "deadline" + # 9 + money = price["money"] + if is_provider and money.get("free") is not True: + ceiling = contract["max_cost"] + if ceiling is None: + if named != name: + return "cost_no_ceiling" + else: + amount, currency = money.get("amount"), money.get("currency") + if not (_is_decimal(amount) and isinstance(currency, str)): + return "cost_unknown" + if currency != ceiling["currency"]: + return "cost_currency" + if fractions.Fraction(amount) > fractions.Fraction(ceiling["amount"]): + return "cost" + if money.get("at_least") is True: + return "cost_at_least" + # 10 + if contract["joules"] is not None: + joules = _value_of(price["energy"].get("joules")) + if not isinstance(price["energy"].get("watch"), str): + return "energy_unwatched" + if joules is not None and joules > contract["joules"]: + return "energy" + return None + + +def _order_key(r): + """§8.7's order: money (free, then an amount in decimals by value, then any other), + time to the nearest millisecond (halves up; a stated one first), local first, + memory, name.""" + p = r["price"] + money = p["money"] + if money.get("free") is True: + cost = (0, fractions.Fraction(0)) + elif _is_decimal(money.get("amount")): + cost = (1, fractions.Fraction(money["amount"])) + else: + cost = (2, fractions.Fraction(0)) + seconds = _value_of(p["time"].get("seconds")) + time = (1, 0) if seconds is None else (0, math.floor(seconds * 1000.0 + 0.5)) + return (cost, time, 0 if r["kind"] == "local" else 1, _value_of(p["memory_bytes"]) or 0.0, r["route"].encode("utf-8")) + + +def _picked(routes, auto, contract, passes): + """§8.7's choice, of the routes the rules let through.""" + let_through = [r for r in routes if passes(r)] + if contract["exactness"] is None and auto is not None: + for r in let_through: + if r["route"] == auto: + return r["route"] + return min(let_through, key=_order_key)["route"] if let_through else None + + +def _stable_holds(p, routes, contract): + """§8.7 stable: routes, digest and choice as the routes give them.""" + stable = p["stable"] + covered = [r for r in routes if r["kind"] == "local" and r["host_dependent"] is False] + facts = [] + for r in covered: + price = r["price"] if isinstance(r["price"], dict) else {} + facts.append({"route": r["route"], "class": r["class"], "seconds": _member(price, "time", "seconds"), + "memory_bytes": price.get("memory_bytes"), "work": price.get("work")}) + digest = blake3(text_of({"job_bytes": p["host"]["job_bytes"], "routes": facts}, True).encode("utf-8")).hex() + names = [r["route"] for r in covered] + others = all(_member(r, "rejected", "code") in ("not_named", "fabric", "class") for r in routes if r["host_dependent"] is not False) + choice = p["choice"] in names and others and contract["providers"] != "allowed" and contract["joules"] is None + return stable.get("routes") == names and stable.get("digest") == digest and stable.get("choice") is choice + + +def _kept_holds(p, contract, result): + """§8.7 kept: exactly a member for each the contract gives, each of exactly its + members, each as its table says.""" + kept = p["kept"] + asked = (("deadline", contract["deadline"] is not None), ("energy", contract["joules"] is not None), ("cost", contract["max_cost"] is not None)) + if len(kept) != sum(1 for _, a in asked if a) or any((n in kept) != a for n, a in asked): + return False + if contract["deadline"] is not None: + d = contract["deadline"] + k = kept["deadline"] + if not _same_keys(k, ("seconds", "elapsed_ms", "kept")): + return False + e = k.get("elapsed_ms") + if not (e is None or (_whole(e) and e.value >= 0)): + return False + want = None if e is None else e.value <= d * 1000.0 + if _value_of(k.get("seconds")) != d or k.get("kept") is not want: + return False + # A method's time is its result's, where its result states one. + if result.get("method") != "provider" and "elapsed_ms" in result and _value_of(result.get("elapsed_ms")) != _value_of(e): + return False + if contract["joules"] is not None: + j = contract["joules"] + k = kept["energy"] + if not _same_keys(k, ("max_joules", "joules", "kept")): + return False + micro = _value_of(_member(result, "energy", "joules_micro")) + stopped = _value_of(_member(result, "stopped", "joules")) + x = stopped if stopped is not None else (None if micro is None else micro / 1e6) + want = False if stopped is not None else (None if x is None else x <= j) + if _value_of(k.get("max_joules")) != j or _value_of(k.get("joules")) != x or k.get("kept") is not want: + return False + if contract["max_cost"] is not None: + ceiling = contract["max_cost"] + k = kept["cost"] + if not _same_keys(k, ("max_cost", "charged", "kept")) or not _same_keys(k.get("max_cost"), ("amount", "currency")): + return False + charged = _member(result, "cost", "charged") + free = _member(result, "cost", "free") + no_free_member = not (isinstance(result.get("cost"), dict) and "free" in result["cost"]) + if charged is not None: + amount = _member(charged, "amount") + if _is_decimal(amount) and _member(charged, "currency") == ceiling["currency"]: + held = fractions.Fraction(amount) <= fractions.Fraction(ceiling["amount"]) + else: + held = None + elif no_free_member or free is True: + held = True + else: + held = None + charged_same = k.get("charged") is None if charged is None else _same(k.get("charged"), charged) + if (_member(k, "max_cost", "amount") != ceiling["amount"] or _member(k, "max_cost", "currency") != ceiling["currency"] + or k.get("kept") is not held or not charged_same): + return False + return True + + +def _count(v): + """§8.7: a count of a list, a whole number written as one from 0 to 2^64 − 1, or 0.""" + if isinstance(v, Num) and v.literal_whole() and not v.text.startswith("-"): + n = int(v.text) + return n if n <= 2 ** 64 - 1 else 0 + return 0 + + +def split_mad(n): + """§8.7: E|2B − n| for B binomial (n, 1/2), in doubles in the order written.""" + if n == 0: + return 0.0 + j = (n - 1) // 2 + if j < 4096: + m = 1.0 + for i in range(j): + m = m * float(2 * i + 3) / float(2 * i + 2) + return m + jj = float(j) + c = (1.0 - 1.0 / (8.0 * jj) + 1.0 / (128.0 * jj * jj) + 5.0 / (1024.0 * jj * jj * jj)) / math.sqrt(math.pi * jj) + return (2.0 * jj + 1.0) * c + + +def shadow_distance(a, b, shots): + """§8.7 distance: the numerator, the denominator, the total variation, the Hellinger + fidelity and the sampling bound, in order, or None when it cannot be taken.""" + if not (isinstance(a, dict) and isinstance(b, dict)) or shots <= 0: + return None + s = float(shots) + numerator, root, bound, total = 0, 0.0, 0.0, 0 + for k in sorted(set(a) | set(b), key=lambda k: k.encode("utf-8")): + x, y = _count(a.get(k)), _count(b.get(k)) + # Sums of whole numbers exact; each product and quotient a double's. + numerator += abs(x - y) + root += math.sqrt(float(x) * float(y)) + total += x + y + bound += split_mad(x + y) + if total > 2 * shots: + return None + denominator = 2 * shots + return (numerator, denominator, float(numerator) / float(denominator), root * root / (s * s), min(1.0, 0.5 * bound / s)) + + +def _whole_value(v): + """A number whose value is whole and at least 0, as a whole number (at most 2^64 − 1).""" + if isinstance(v, Num) and float(v.value).is_integer() and v.value >= 0: + return min(int(v.value), 2 ** 64 - 1) + return None + + +def _shadow_count(v): + """§8.7: a count of a shadow's list, a whole number written as one from 1 to 2^53 − 1.""" + if isinstance(v, Num) and v.literal_whole() and not v.text.startswith("-"): + n = int(v.text) + if 1 <= n <= MAX_SAFE: + return n + return None + + +def _shadow_budget(contract, provider_seconds): + d = contract["deadline"] + if d is None: + return 300.0 + if provider_seconds is None: + return d + return max(d - provider_seconds, 0.0) + + +def _shadow_plan_holds(request, contract, p, result): + """§8.7: the reasoning's shadow.""" + plan = p.get("shadow") + if not isinstance(plan, dict) or "route" not in plan: + return False + route = plan["route"] + if route is None: + return (plan.get("code") in ("budget", "memory", "none") and isinstance(plan.get("why"), str) + and ("tried" not in plan or isinstance(plan["tried"], list))) + if not (isinstance(route, str) and route.startswith("method:") and len(route) > 7): + return False + chosen = next((r for r in p["routes"] if r["route"] == p["choice"]), None) + provider_seconds = _value_of(_member(chosen, "price", "time", "seconds")) if chosen else None + budget = _shadow_budget(contract, provider_seconds) + req = plan.get("request") + price = plan.get("price") + listed = next((r for r in p["routes"] if r["route"] == route), None) + if listed is None or plan.get("class") != listed["class"]: + return False + if not (plan.get("class") in LADDER and _value_of(plan.get("budget_seconds")) == budget + and _price_form(price, True) and _value_of(_member(price, "time", "seconds")) is not None + and _value_of(price["time"]["seconds"]) <= budget): + return False + if not _same_keys(req, ("qasm", "shots", "seed", "method")): + return False + seed = request.get("seed") + seed = int(seed.text) if isinstance(seed, Num) and seed.literal_whole() and not seed.text.startswith("-") else 1 + seed = seed if seed <= 2 ** 64 - 1 else 1 + want_seed = (seed + 2 ** 32) % 2 ** 53 + given = req.get("seed") + return (_same(req.get("qasm"), request.get("qasm")) and isinstance(req.get("qasm"), str) + and _same(req.get("shots"), result.get("shots")) + and isinstance(given, Num) and given.literal_whole() and not given.text.startswith("-") and int(given.text) == want_seed + and req.get("method") == route[len("method:"):]) + + +def _shadow_holds(request, contract, p, result): + """§8.7 shadow: its plan, its form, what its plan and the job imply, its distance its + counts'.""" + s, plan = result["shadow"], p.get("shadow") + if not isinstance(s, dict) or not _shadow_plan_holds(request, contract, p, result): + return False + ran = s.get("ran") + if ran is False: + if not (isinstance(s.get("code"), str) and isinstance(s.get("why"), str)): + return False + return s["code"] == plan.get("code") if plan.get("route") is None else s["code"] == "failed" + if ran is not True or plan.get("route") is None: + return False + shots = _whole_value(result.get("shots")) + counts = s.get("counts") + if not isinstance(counts, dict) or shots is None: + return False + listed = [_shadow_count(v) for v in counts.values()] + omitted = _whole_value(s.get("omitted_shots")) + if any(n is None for n in listed) or omitted is None or sum(listed) + omitted != shots: + return False + if not (_whole(s.get("distinct_outcomes")) and s["distinct_outcomes"].value >= 0): + return False + # Its outcomes are a counts' form: of 0 and 1, as wide as the job's where the + # provider's counts name one; with none omitted, as said. + theirs = result.get("counts") + width = len(next(iter(theirs), "")) if isinstance(theirs, dict) and theirs else len(next(iter(counts), "")) + if any(len(k) != width or set(k) - {"0", "1"} for k in counts) or (omitted == 0 and s["distinct_outcomes"].value != len(counts)): + return False + d = s.get("distance") + if not isinstance(d, dict): + return False + # By value: an omitted_shots of 0 however it is written. + theirs, ours = _value_of(result.get("omitted_shots")), _value_of(s.get("omitted_shots")) + if d.get("computed") is False: + if not isinstance(d.get("why"), str) or (theirs == 0 and ours == 0): + return False + elif d.get("computed") is True: + if "distance-unchecked" not in PLANTS: # PLANT + want = shadow_distance(result.get("counts"), counts, shots) + if want is None or theirs != 0 or ours != 0: + return False + for k, v in zip(("numerator", "denominator", "total_variation", "hellinger_fidelity", "sampling_tvd_bound"), want): + if _value_of(d.get(k)) != float(v): + return False + else: + return False + cls = _member(s, "accuracy", "class") + if not _class_of_method(plan["route"][len("method:"):], cls): + return False + return (s.get("route") == plan["route"] and isinstance(cls, str) and meets(plan.get("class"), cls) + and _same(s.get("request"), plan.get("request")) and _same(s.get("shots"), result.get("shots"))) + + +STOPPED_MEMBERS = ("method", "qubits", "gates", "accuracy", "stopped", "elapsed_ms", "planner", "energy", "engine", "schema", "receipt") + + +def _stopped_holds(contract, result): + """§8.7: a run stopped at its ceiling, on a contract that gives one, a reading at or + past it, on a method's run, with no answer.""" + s = result["stopped"] + j = contract["joules"] + if not _same_keys(s, ("at", "joules", "max_joules", "elapsed_ms", "read")) or j is None: + return False + x = _value_of(s.get("joules")) + return (s.get("at") == "max_joules" and _value_of(s.get("max_joules")) == j and x is not None and x >= j + and _whole(s.get("elapsed_ms")) and s["elapsed_ms"].value >= 0 and isinstance(s.get("read"), str) + and result.get("method") != "provider" and _member(result, "accuracy", "class") == "none" + and all(k in STOPPED_MEMBERS for k in result) + and (_value_of(_member(result, "energy", "joules_micro")) is None or _value_of(_member(result, "energy", "joules_micro")) >= x * 1e6 - 1.0) + and _value_of(result.get("elapsed_ms")) == _value_of(s.get("elapsed_ms"))) + + +def check_contract(request, result, reasons): + # §8.7. A job with no contract carries neither a reasoning nor a shadow. + given = request.get("contract") + planner = result.get("planner") + if given is None: + if "planner" in result: + reasons.add("planner_form") + if "shadow" in result: + reasons.add("shadow") + if "stopped" in result: + reasons.add("stopped") + return + contract = read_contract(given) + if contract is None: + reasons.add("contract_form") + return + if not _planner_form(planner): + reasons.add("planner_form") + return + if request.get("provider") is not None and contract["providers"] != "allowed": + reasons.add("contract_provider") + routes = planner["routes"] + # The providers the host brought are its provider routes, in their order. + brought = [r["route"][len("provider:"):] for r in routes if r["kind"] == "provider"] + if planner["host"]["providers"] != brought: + reasons.add("planner_form") + return + # What the job names, the question it asks and what auto picks: from the request + # and the routes, never from what the reasoning says of itself. + named = _request_names(request) + if named is None and request.get("target") is not None: + stated = planner.get("named") + named = stated if isinstance(stated, str) and stated.startswith("method:") else None + question = _question(request) + ranks_ok = True + for r in routes: + if r["kind"] == "local" and r["route"][len("method:"):] in AUTO_RANKS: + want = AUTO_RANKS[r["route"][len("method:"):]][QUESTIONS.index(question)] + if _value_of(r["auto_rank"]) != want: + ranks_ok = False + auto = _auto(routes, request, named) + class_of = dict((r["route"], r["class"]) for r in routes) + if contract["exactness"] is not None: + wanted, source = contract["exactness"], "contract" + elif named is not None: + wanted, source = class_of.get(named), "named" + elif auto is not None: + wanted, source = class_of.get(auto), "auto" + else: + wanted, source = None, None + if (planner.get("named") != named or planner.get("question") != question or not ranks_ok + or planner.get("auto") != auto or planner.get("wanted") != wanted or planner["wanted_from"] != source): + reasons.add("planner_form") + return + job_bytes = planner["host"]["job_bytes"].value + from_contract = source == "contract" + + def gate(r): + return _gate(r, contract, request, named, wanted, from_contract, job_bytes) + + broken = False + chosen = [r["route"] for r in routes if r["outcome"] == "chosen"] + if "route-unchecked" not in PLANTS: # PLANT + for r in routes: + if _member(r, "rejected", "code") != gate(r) or not _states_itself(r, request): + broken = True + if len(chosen) != 1 or chosen[0] != planner["choice"]: + broken = True + if broken: + reasons.add("planner_route") + if result.get("method") == "provider": + name = _member(result, "provider", "name") + ran = "provider:" + name if isinstance(name, str) else None + else: + m = result.get("method") + ran = "method:" + m if isinstance(m, str) else None + if "choice-unchecked" not in PLANTS: # PLANT + if (_picked(routes, auto, contract, lambda r: gate(r) is None) != planner["choice"] or ran != planner["choice"] + or not _ran_as_routed(routes, planner["choice"], result)): + reasons.add("planner_choice") + if not _stable_holds(planner, routes, contract): + reasons.add("planner_stable") + if not _kept_holds(planner, contract, result): + reasons.add("planner_kept") + cls = _member(result, "accuracy", "class") + short = wanted is not None and (not meets(wanted, cls) or (from_contract and wanted == "simulated" and _member(result, "accuracy", "approximate") is True)) + # A method's result has a class its method has. + method = result.get("method") + if "stopped" in result: + if not _stopped_holds(contract, result): + reasons.add("stopped") + elif short or (isinstance(method, str) and method != "provider" and not _class_of_method(method, cls)): + reasons.add("contract_class") + # Under a contract a provider's result is of the current form. + if result.get("method") == "provider" and ("counts_source" not in result or "execution" not in result): + reasons.add("contract_form") + is_provider = planner["choice"].startswith("provider:") + if is_provider != ("shadow" in result) or is_provider != ("shadow" in planner) or (is_provider and not _shadow_holds(request, contract, planner, result)): + reasons.add("shadow") + + +def contract_statement(result): + """§8.7: what a verifier states of a job under a contract.""" + p = result.get("planner") + return { + "choice": _plain(_member(p, "choice")), + "wanted": _plain(_member(p, "wanted")), + "class": _plain(_member(result, "accuracy", "class")), + "stable_choice": _plain(_member(p, "stable", "choice")), + "kept": _plain(_member(p, "kept")), + "shadow_ran": _plain(_member(result, "shadow", "ran")), + "shadow_total_variation": _plain(_member(result, "shadow", "distance", "total_variation")), + } + + # ===================================================================== 7. a job def _verdict(reasons, key=None, form=None): @@ -1070,9 +1867,12 @@ def judge_job(request, result): check_provider(request, result, reasons) else: check_class(result, False, False, reasons) + check_contract(request, result, reasons) verdict = _verdict(reasons, key, form) if provider: verdict["provider"] = provider_statement(result) + if "planner" in result: + verdict["planner"] = contract_statement(result) return verdict @@ -1489,6 +2289,102 @@ def _provider_result(**changes): _DELETE = object() +def _contract_job(seed=None, extra_routes=(), **changes): + """§8.7: the provider job above, named under a contract that allows it and wants a + simulator's counts, with its reasoning and its shadow, for the self-test only: + (request text, result text). Every outcome is written here, not computed.""" + request = json.loads(_PROVIDER_REQUEST) + request["contract"] = {"exactness": "simulated", "providers": "allowed"} + if seed is not None: + request["seed"] = seed + job_bytes = 1 << 30 + facts = {"job_bytes": job_bytes, "routes": [ + {"route": "method:exact", "class": "bit-exact", "seconds": None, "memory_bytes": None, "work": None}]} + digest = blake3(text_of(read_json(json.dumps(facts).encode()), True).encode("utf-8")).hex() + shadow_request = {"qasm": request["qasm"], "shots": 4, "seed": ((1 if seed is None else seed) + 2 ** 32) % 2 ** 53, "method": "exact"} + free_now = {"money": {"free": True}, "time": {"seconds": 1.5, "basis": "provider"}, "memory_bytes": None, + "work": None, "energy": {"joules": None, "why": "no provider states it"}, "leaves_out": ["energy"]} + planner = { + "format": "wai.quantum.planner/1", "wanted": "simulated", "wanted_from": "contract", + "named": "provider:lab", "question": "counts", "auto": None, + "host": {"job_bytes": job_bytes, "providers": ["lab"] + [r["provider"] for r in extra_routes]}, + "routes": [ + {"route": "method:exact", "kind": "local", "method": "exact", "class": "bit-exact", "host_dependent": False, + "auto_rank": 20, "price": None, "outcome": "rejected", "rejected": {"code": "not_named", "why": "the job names another route"}}, + {"route": "provider:lab", "kind": "provider", "provider": "lab", "class": "simulated", "host_dependent": True, + "price": free_now, "outcome": "chosen"}, + ] + list(extra_routes), + "choice": "provider:lab", "why": "the route the job names", + "stable": {"scope": "the host-independent routes", "routes": ["method:exact"], "digest": digest, "choice": False}, + "kept": {}, + "shadow": {"route": "method:exact", "class": "bit-exact", "budget_seconds": 300, + "price": {"money": {"free": True}, "time": {"seconds": 0.001, "basis": "nominal"}, "memory_bytes": 1024, + "work": 8, "energy": {"joules": None, "why": "none"}, "leaves_out": []}, + "request": shadow_request}, + } + # By hand: 8 shots of "1" pooled, E|2B - 8| = (3/2)(5/4)(7/6) = 2.1875; half of it over 4. + n, d, tv, hf, bound = 0, 8, 0.0, 1.0, 0.2734375 + shadow = {"ran": True, "route": "method:exact", "request": shadow_request, "shots": 4, + "accuracy": {"class": "bit-exact"}, "counts": {"1": 4}, "distinct_outcomes": 1, "omitted_shots": 0, + "distance": {"computed": True, "numerator": n, "denominator": d, "total_variation": tv, + "hellinger_fidelity": hf, "sampling_tvd_bound": bound}} + result = json.loads(_provider_result()) + result["planner"], result["shadow"] = planner, shadow + both = {"request": request, "result": result} + for path, value in changes.items(): + node = both + parts = path.split("__") + for part in parts[:-1]: + node = node[int(part)] if isinstance(node, list) else node[part] + last = int(parts[-1]) if isinstance(node, list) else parts[-1] + if value is _DELETE: + node.pop(last) + else: + node[last] = value + return json.dumps(both["request"], separators=(",", ":")), json.dumps(both["result"], separators=(",", ":")) + + +def _lr(name, cls, rank, outcome, code=None, seconds=0.001, memory=1024, joules=None, host_dependent=False, priced=True, watch="a test's reading"): + """A local route, every member written out, for the self-test only.""" + r = {"route": "method:" + name, "kind": "local", "method": name, "class": cls, "host_dependent": host_dependent, + "auto_rank": rank, "outcome": outcome, + "price": {"money": {"free": True}, "time": {"seconds": seconds, "basis": "nominal"}, "memory_bytes": memory, + "work": 8, "energy": {"joules": joules, "basis": "a test"} if joules is not None else {"joules": None, "why": "none"}, + "leaves_out": []} if priced else None} + if priced and watch is not None: + r["price"]["energy"]["watch"] = watch + if code: + r["rejected"] = {"code": code, "why": "said so"} + return r + + +def _local_contract_job(contract, routes, choice, auto, stable_choice, kept, request_extra=None, energy=None, providers=(), result_class="bit-exact"): + """§8.7: a job under a contract run on one of the engine's methods, for the self-test + only: (request text, result text). Every outcome, the choice, auto and stable.choice + are written by the caller, never computed here.""" + request = {"qasm": "OPENQASM 3.0;\nqubit[1] q;\nbit[1] c;\nx q[0];\nc = measure q;\n", "shots": 4, "contract": contract} + request.update(request_extra or {}) + job_bytes = 1 << 30 + covered = [r for r in routes if r["kind"] == "local" and r["host_dependent"] is False] + facts = {"job_bytes": job_bytes, "routes": [{"route": r["route"], "class": r["class"], + "seconds": (r["price"] or {}).get("time", {}).get("seconds"), "memory_bytes": (r["price"] or {}).get("memory_bytes"), + "work": (r["price"] or {}).get("work")} for r in covered]} + digest = blake3(text_of(read_json(json.dumps(facts).encode()), True).encode("utf-8")).hex() + wanted = contract.get("exactness") + planner = { + "format": "wai.quantum.planner/1", "wanted": wanted, "wanted_from": "contract" if wanted else None, + "named": None, "question": "counts", "auto": auto, + "host": {"job_bytes": job_bytes, "providers": list(providers)}, "routes": routes, "choice": choice, + "why": "the cheapest", "kept": kept, + "stable": {"scope": "the host-independent routes", "routes": [r["route"] for r in covered], "digest": digest, "choice": stable_choice}, + } + result = {"method": choice[len("method:"):], "qubits": 1, "gates": 1, "accuracy": {"class": result_class}, + "counts": {"1": 4}, "elapsed_ms": 3, "planner": planner, + "energy": energy if energy is not None else {"unmetered": "a test"}, + "engine": {"name": "wai-quantum", "version": "0.9.0"}, "schema": "wai.quantum.job-result/1"} + return json.dumps(request, separators=(",", ":")), json.dumps(result, separators=(",", ":")) + + def _has_num(o): if isinstance(o, Num): return True @@ -2030,6 +2926,273 @@ def self_test(args): finally: PLANTS.discard(plant) + # §8.7: a job under a contract, as it is and broken one way at a time. + def contract_body(job_seed=None, extra_routes=(), **changes): + return _seal(seed, *_contract_job(seed=job_seed, extra_routes=extra_routes, **changes)) + + def local_body(contract, routes, choice, auto, stable_choice, kept, **kw): + return _seal(seed, *_local_contract_job(contract, routes, choice, auto, stable_choice, kept, **kw)) + + def stopped_body(**changes): + request, result = _local_contract_job({"exactness": "exact", "max_joules": 2}, [ + _lr("exact", "bit-exact", 20, "chosen", joules=1.0), _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, + {"energy": {"max_joules": 2, "joules": 2.5, "kept": False}}, result_class="none") + both = {"request": json.loads(request), "result": json.loads(result)} + del both["result"]["counts"] + both["result"]["stopped"] = {"at": "max_joules", "joules": 2.5, "max_joules": 2, "elapsed_ms": 3, "read": "a test's reading"} + for path, value in changes.items(): + node = both + parts = path.split("__") + for part in parts[:-1]: + node = node[part] + if value is _DELETE: + del node[parts[-1]] + else: + node[parts[-1]] = value + return _seal(seed, json.dumps(both["request"], separators=(",", ":")), json.dumps(both["result"], separators=(",", ":"))) + + def energy_routes(statevector): + return local_body({"exactness": "exact", "max_joules": 2}, [ + _lr("exact", "bit-exact", 20, "chosen", joules=1.0), statevector, + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, + {"energy": {"max_joules": 2, "joules": 2.0, "kept": True}}, energy={"joules_micro": 2000000}) + + def read_and_not(): + r = _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0) + r["price"]["energy"]["unwatched"] = "and yet" + return r + + check("a stop on a provider's run, which nothing here reads", "stopped" in reasons_of(stopped_body(result__method="provider"))) + + def contract_edited(edit): + request, text = _contract_job(seed=None, extra_routes=()) + body = {"request": json.loads(request), "result": json.loads(text)} + edit(body) + return _seal(seed, json.dumps(body["request"], separators=(",", ":")), json.dumps(body["result"], separators=(",", ":"))) + + def chosen(b): + return next(r for r in b["result"]["planner"]["routes"] if r["route"] == b["result"]["planner"]["choice"]) + + check("a run sealed at a cost its route does not state", reasons_of(contract_edited( + lambda b: b["result"]["cost"].update(free=False, confirmed=True, estimate={"free": False, "amount": "50", "currency": "USD"}))) == ["planner_choice"]) + check("the route chosen names another device than ran", reasons_of(contract_edited(lambda b: chosen(b).update(device="elsewhere"))) == ["planner_choice"]) + check("members alike by value: 7 and 7.0, -0 and 0", _alike(Num("7", 7.0), Num("7.0", 7.0)) and _alike(Num("-0", -0.0), Num("0", 0.0))) + check("a boolean is no number, and null is absent", not _alike(True, Num("1", 1.0)) and _alike(None, None) and not _alike("a", None)) + check("lists and objects alike member by member", _alike([Num("7", 7.0)], [Num("7.0", 7.0)]) and _alike({"a": Num("-0", -0.0), "b": None}, {"a": Num("0", 0.0)}) + and not _alike([True], [Num("1", 1.0)]) and not _alike({"a": "x"}, {"a": "y"})) + check("an earlier-form provider result under a contract", "contract_form" in reasons_of(contract_edited( + lambda b: [b["result"].pop(k) for k in ("counts_source", "execution")]))) + check("the route chosen names the device that ran", reasons_of(contract_edited(lambda b: chosen(b).update(device=b["result"]["provider"]["device"]))) == []) + + def timed_by_host(kept): + request, text = _local_contract_job({"exactness": "exact", "deadline_seconds": 60}, base(), "method:exact", "method:exact", True, kept) + result = json.loads(text) + del result["elapsed_ms"] + return _seal(seed, request, json.dumps(result, separators=(",", ":"))) + + contract_ok = contract_body() + check("a contract job's reasoning and shadow", reasons_of(contract_ok) == []) + for name, raw_case, want in ( + ("a contract that does not read", contract_body(request__contract={"exactness": "nearly"}), ["contract_form"]), + ("a reasoning dropped", contract_body(result__planner=_DELETE), ["planner_form"]), + ("a digest not the routes'", contract_body(result__planner__stable__digest="00" * 32), ["planner_stable"]), + ("a choice said to be the host's own", contract_body(result__planner__stable__choice=True), ["planner_stable"]), + ("a kept the contract does not ask", contract_body(result__planner__kept={"deadline": {}}), ["planner_kept"]), + ("a class short of what is wanted", contract_body(result__accuracy__approximate=True), ["contract_class"]), + ("a shadow on another seed", contract_body(result__shadow__request__seed=4), ["shadow"]), + ("a shadow's omitted_shots of 0.0", contract_body(result__shadow__omitted_shots=0.0), []), + ("a distance not computed, every shot listed", contract_body( + result__shadow__distance={"computed": False, "why": "said so"}), ["shadow"]), + ("the least it can come to, on a free route", contract_body( + result__planner__routes__1__price__money={"free": True, "at_least": False}), ["planner_form"]), + ("a named provider under never", contract_body(request__contract__providers="never"), + ["contract_provider", "planner_choice", "planner_route"]), + ("a shadow request with a noise model", contract_body( + result__planner__shadow__request__noise={"depolarizing_2q": 0.2}, + result__shadow__request__noise={"depolarizing_2q": 0.2}), ["shadow"]), + ("a route with no watch, said to meet a ceiling", energy_routes(_lr("statevector", "exact", 30, "met", memory=2048, joules=1.0, watch=None)), ["planner_route"]), + ("a watched route said to have no reading", energy_routes(_lr("statevector", "exact", 30, "rejected", "energy_unwatched", memory=2048, joules=1.0)), ["planner_route"]), + ("a watch that is no sentence", local_body({"exactness": "exact", "max_joules": 2}, [ + _lr("exact", "bit-exact", 20, "chosen", joules=1.0), _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0, watch=True), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, + {"energy": {"max_joules": 2, "joules": 2.0, "kept": True}}, energy={"joules_micro": 2000000}), ["planner_form"]), + ("a run stopped past no ceiling it has", stopped_body(result__stopped__max_joules=9), ["stopped"]), + ("a run stopped under its ceiling", stopped_body(result__stopped__joules=1.5, result__planner__kept__energy__joules=1.5), ["stopped"]), + ("a stopped run that gives an answer", stopped_body(result__counts={"1": 4}), ["stopped"]), + ("a stopped run said to have kept its ceiling", stopped_body(result__planner__kept__energy__kept=True), ["planner_kept"]), + ("a run stopped with no ceiling", stopped_body(request__contract={"exactness": "exact"}), ["planner_kept", "planner_stable", "stopped"]), + ("a run stopped with no contract", stopped_body(request__contract=_DELETE), ["planner_form", "stopped"]), + ("a reading exactly at the ceiling stops a run", stopped_body(result__stopped__joules=2, result__planner__kept__energy__joules=2), []), + ("a stopped run that claims a class", stopped_body(result__accuracy__class="exact"), ["stopped"]), + ("a stop that does not say what read it", stopped_body(result__stopped__read=7), ["stopped"]), + ("a stop at a time that is no whole number", stopped_body(result__stopped__elapsed_ms=1.5), ["stopped"]), + ("a stop with a member its form does not have", stopped_body(result__stopped__note="more"), ["stopped"]), + ("a stop at something other than the energy ceiling", stopped_body(result__stopped__at="deadline"), ["stopped"]), + ("an estimate exactly at the ceiling refuses nothing", energy_routes(_lr("statevector", "exact", 30, "met", memory=2048, joules=2.0)), []), + ("a route said both to be read and to have no reading", energy_routes(read_and_not()), ["planner_form"]), + # By hand: "1" 4 and 1 times, 5 pooled, E|2B - 5| = 1.875; half of it over 4. + ("a shadow's counts short of its shots, the distance what they give", contract_body( + result__shadow__counts={"1": 1}, + result__shadow__distance={"computed": True, "numerator": 3, "denominator": 8, "total_variation": 0.375, + "hellinger_fidelity": 0.25, "sampling_tvd_bound": 0.234375}), ["shadow"]), + # By hand: "1" 4 and "x" 4 times, each pooled 4, E|2B - 4| = 1.5 twice; half of it over 4. + ("a shadow's outcomes that are not bits, the distance what they give", contract_body( + result__shadow__counts={"x": 4}, + result__shadow__distance={"computed": True, "numerator": 8, "denominator": 8, "total_variation": 1.0, + "hellinger_fidelity": 0.0, "sampling_tvd_bound": 0.375}), ["shadow"]), + ("a shadow that says more outcomes than it lists", contract_body(result__shadow__distinct_outcomes=7), ["shadow"]), + ("a shadow's class its method does not have", contract_body( + result__planner__routes__0__route="method:mps", result__planner__routes__0__method="mps", + result__planner__routes__0__class="heuristic", result__planner__routes__0__auto_rank=60, result__planner__stable__routes=["method:mps"], + result__planner__shadow__route="method:mps", result__planner__shadow__class="heuristic", + result__planner__shadow__request__method="mps", result__shadow__route="method:mps", + result__shadow__request__method="mps"), ["planner_stable", "shadow"]), + ("host.providers that are not its provider routes", contract_body(result__planner__host__providers=["someone-else"]), ["planner_form"]), + ("a provider that states its memory", contract_body(result__planner__routes__1__price__memory_bytes=1024), ["planner_form"]), + ("a provider's route said not to depend on the host", contract_body(result__planner__routes__1__host_dependent=False), ["planner_route"]), + ("a method on no GPU said to depend on the host", contract_body(result__planner__routes__0__host_dependent=True), ["planner_route", "planner_stable"]), + ("a built-in route stated a class it does not have", contract_body(result__planner__routes__0__class="exact"), ["planner_route", "planner_stable", "shadow"]), + ("a method's result of a class it does not have", local_body({"exactness": "exact"}, [ + _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {}, result_class="exact"), ["contract_class"]), + ("a method's memory that is not stated", local_body({"exactness": "exact"}, [ + _lr("exact", "bit-exact", 20, "chosen"), dict(_lr("statevector", "exact", 30, "met"), price={"money": {"free": True}, "time": {"seconds": 0.001, "basis": "nominal"}, "memory_bytes": None, "work": 8, "energy": {"joules": None, "why": "none"}, "leaves_out": []}), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {}), ["planner_form"]), + ("a shadow planned at a class its route is not listed with", + contract_body(result__planner__shadow__class="heuristic"), ["shadow"]), + ("a time past what a price states", contract_body(result__planner__routes__1__price__time__seconds=1e306), ["planner_form"]), + ): + check(name, reasons_of(raw_case) == want) + + # §8.7, rule by rule: each case is valid, and a verifier that bends the rule it + # holds to gives it a reason. Every outcome is written here by hand. + approx = {"route": "provider:approx", "kind": "provider", "provider": "approx", "class": "simulated", + "host_dependent": True, "approximate": True, "outcome": "rejected", + "rejected": {"code": "class", "why": "approximate"}, + "price": {"money": {"free": True}, "time": {"seconds": 1.0, "basis": "provider"}, "memory_bytes": None, + "work": None, "energy": {"joules": None, "why": "none"}, "leaves_out": ["energy"]}} + sim = dict(approx, provider="sim", route="provider:sim", outcome="met") + del sim["approximate"], sim["rejected"] + sim["price"] = dict(approx["price"], time={"seconds": 0.0, "basis": "provider"}) + + def base(cls_of_sv_single="class", **kw): + return [_lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048, **kw), + _lr("statevector_single", "single", 40, "rejected", cls_of_sv_single, host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)] + routed = dict(request__provider=_DELETE, result__planner__named=None, result__planner__routes__0__rejected__code="class") + ceiling = {"exactness": "simulated", "providers": "allowed", "max_cost": {"amount": "1", "currency": "USD"}} + kept_free = {"cost": {"max_cost": {"amount": "1", "currency": "USD"}, "charged": None, "kept": True}} + + def provider_route(name, money, code, seconds=1.0): + return {"route": "provider:" + name, "kind": "provider", "provider": name, "class": "simulated", "host_dependent": True, + "outcome": "rejected", "rejected": {"code": code, "why": "said so"}, + "price": {"money": money, "time": {"seconds": seconds, "basis": "provider"}, "memory_bytes": None, + "work": None, "energy": {"joules": None, "why": "none"}, "leaves_out": ["energy"]}} + sim_never = provider_route("sim", {"free": True}, "providers", seconds=0.0) + for name, raw_case, want in ( + ("the least it can come to is not within a ceiling", contract_body( + extra_routes=(provider_route("least", {"free": False, "amount": "0.1", "currency": "USD", "at_least": True}, "cost_at_least"),), + request__contract=ceiling, result__planner__kept=kept_free, **routed), []), + ("a ceiling in another currency is not met", contract_body( + extra_routes=(provider_route("euro", {"free": False, "amount": "0.1", "currency": "EUR"}, "cost_currency"),), + request__contract=ceiling, result__planner__kept=kept_free, **routed), []), + ("a cost with no ceiling is not met", contract_body( + extra_routes=(provider_route("paid", {"free": False, "amount": "0.1", "currency": "USD"}, "cost_no_ceiling"),), **routed), []), + ("a charge the result does not state", contract_body( + request__contract=ceiling, result__planner__kept={"cost": dict(kept_free["cost"], charged={"amount": "0", "currency": "USD"})}, **routed), + ["planner_kept"]), + ("a planned shadow said not to have run", contract_body(result__shadow={"ran": False, "code": "none", "why": "said so"}), ["shadow"]), + ("a plan's code that no plan has", contract_body( + result__planner__shadow={"route": None, "code": "failed", "why": "said so"}, + result__shadow={"ran": False, "code": "failed", "why": "said so"}), ["shadow"]), + ("a provider under never, beside a local route", local_body({"exactness": "any"}, [ + _lr("exact", "bit-exact", 20, "chosen", seconds=0.0001), _lr("statevector", "exact", 30, "met", seconds=0.0001, memory=2048), + _lr("statevector_single", "single", 40, "rejected", "cannot", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "met", seconds=0.0001, memory=4096), sim_never], "method:exact", "method:exact", False, {}, + providers=("sim",)), []), + ("a time not known does not meet a deadline", local_body({"exactness": "exact", "deadline_seconds": 60}, [ + _lr("exact", "bit-exact", 20, "chosen"), dict(_lr("statevector", "exact", 30, "rejected", "deadline_unknown"), + price=dict(_lr("statevector", "exact", 30, "met")["price"], time={"seconds": None, "why": "not known"})), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, + {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), []), + ("a deadline a host's timer kept, the result stating no time of its own", timed_by_host({"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), []), + ("the matrix product state's route stated exact", local_body({"exactness": "exact", "deadline_seconds": 60}, base()[:3] + [_lr("mps", "exact", 60, "met", memory=4096)], + "method:exact", "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), ["planner_route"]), + ("a method the host registered, said not to depend on the host", local_body({"exactness": "exact", "deadline_seconds": 60}, base() + [_lr("turbo", "bit-exact", None, "met")], + "method:exact", "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), ["planner_route"]), + ("the same, said to depend on it", local_body({"exactness": "exact", "deadline_seconds": 60}, base() + [_lr("turbo", "bit-exact", None, "met", host_dependent=True)], + "method:exact", "method:exact", False, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), []), + ("a deadline's time that is not the result's", local_body({"exactness": "exact", "deadline_seconds": 60}, base(), "method:exact", + "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 4, "kept": True}}), + ["planner_kept"]), + ("auto said to be another route", local_body({"exactness": "exact"}, base(), "method:exact", "method:statevector", True, {}), ["planner_form"]), + ("a built-in method's rank not its own", local_body({"exactness": "exact"}, [ + _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048), + _lr("statevector_single", "single", 0, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {}), ["planner_form"]), + ("a local route that costs money", local_body({"exactness": "exact"}, [ + _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + dict(_lr("mps", "heuristic", 60, "rejected", "class", memory=4096), + price=dict(_lr("mps", "heuristic", 60, "met")["price"], money={"free": False, "unknown": "a host's word"}))], + "method:exact", "method:exact", True, {}), ["planner_form"]), + ("a ceiling past 64 characters", local_body({"exactness": "exact", "max_cost": {"amount": "1" * 65, "currency": "USD"}}, base(), + "method:exact", "method:exact", True, + {"cost": {"max_cost": {"amount": "1" * 65, "currency": "USD"}, "charged": None, "kept": True}}), + ["contract_form"]), + ): + check("rule: " + name, reasons_of(raw_case) == want) + # The distance in its order, by hand: three shots of "1" against "0" twice and "1" + # once. R = sqrt(3), and R*R/(S*S) is 0.33333333333333326, where (R/S)^2 is not. + three = contract_body( + request__shots=3, result__shots=3, result__counts={"1": 3}, + result__planner__shadow__request__shots=3, result__shadow__request__shots=3, result__shadow__shots=3, + result__shadow__counts={"0": 2, "1": 1}, result__shadow__distinct_outcomes=2, + result__shadow__distance={"computed": True, "numerator": 4, "denominator": 6, "total_variation": 4 / 6, + "hellinger_fidelity": 0.33333333333333326, "sampling_tvd_bound": 0.4166666666666667}) + check("rule: the Hellinger fidelity in its order", reasons_of(three) == []) + for name, raw_case in ( + # Routed, no provider named: the approximate one is quicker, and not met. + ("an approximate simulator does not meet simulated", contract_body( + extra_routes=(approx,), request__provider=_DELETE, result__planner__named=None, + result__planner__routes__0__rejected__code="class")), + ("the shadow's seed wraps at 2^53", contract_body(job_seed=2 ** 53 - 2)), + ("single does not meet bounded", local_body({"exactness": "bounded"}, base(), "method:exact", "method:exact", True, {})), + ("a job's memory at its cap", local_body({"exactness": "exact"}, [ + _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=1 << 30), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {})), + ("a GPU's method off the CPU", local_body({"exactness": "single"}, base("fabric"), "method:exact", "method:exact", True, {}, + request_extra={"fabric": "cpu"})), + ("energy at its ceiling, and a host's estimate", local_body({"exactness": "exact", "max_joules": 2}, [ + _lr("exact", "bit-exact", 20, "chosen", joules=1.0), _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0), + _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, + {"energy": {"max_joules": 2, "joules": 2.0, "kept": True}}, energy={"joules_micro": 2000000})), + ("a route no reading can stop, refused under a ceiling", energy_routes(_lr("statevector", "exact", 30, "rejected", "energy_unwatched", memory=2048, joules=1.0, watch=None))), + ("an estimate past the ceiling refuses a watched route", energy_routes(_lr("statevector", "exact", 30, "rejected", "energy", memory=2048, joules=3.0))), + ("a run stopped at its ceiling, and said so", stopped_body()), + ("an approximate simulator named, under a contract that names no class", contract_body( + request__contract={"providers": "allowed"}, result__planner__wanted_from="named", + result__planner__routes__1__approximate=True)), + ("a local route before a provider's at one time", local_body({"exactness": "any", "providers": "allowed"}, [ + _lr("exact", "bit-exact", 20, "chosen", seconds=0.0001), _lr("statevector", "exact", 30, "met", seconds=0.0001, memory=2048), + _lr("statevector_single", "single", 40, "rejected", "cannot", host_dependent=True, priced=False), + _lr("mps", "heuristic", 60, "met", seconds=0.0001, memory=4096), sim], "method:exact", "method:exact", False, {}, + providers=("sim",))), + ): + check("rule: " + name, reasons_of(raw_case) == []) + unnamed_route = contract_body(result__planner__routes__0__outcome="met", result__planner__routes__0__rejected=_DELETE) + another_answered = contract_body(result__provider__name="other") + distance_said = contract_body(result__shadow__distance__numerator=1) + simulator_measured = provider_body(accuracy__class="measured") duplicated = body.replace(b'{"request"', b'{"why":"a","why":"b","request"') plant_cases = ( @@ -2043,6 +3206,9 @@ def self_test(args): ("no-canonical-spelling", seeded("1152921504606847000"), [], ["inexact_number"]), ("set-seal-only", set_of(2, head_extra={"count": 3}), ["set_items"], []), ("names-layout-only", names_short, ["provider_members"], []), + ("route-unchecked", unnamed_route, ["planner_route"], []), + ("choice-unchecked", another_answered, ["planner_choice", "request_provider"], ["request_provider"]), + ("distance-unchecked", distance_said, ["shadow"], []), ) for plant, raw, strict, lenient in plant_cases: check("plant %s: strict verdict" % plant, reasons_of(raw) == strict) diff --git a/wai/quantum-studio/build-views.mjs b/wai/quantum-studio/build-views.mjs index cf347e438..fad65a893 100644 --- a/wai/quantum-studio/build-views.mjs +++ b/wai/quantum-studio/build-views.mjs @@ -1,7 +1,9 @@ // Build the views an agent host draws (src/views/) into one self-contained // page: the view's script (the Studio's components, bundled), the Studio's // styles, and the engine inside the view (wai/wai-quantum-views) twice, as -// WebAssembly (base64) and as the same build translated to JavaScript. The page +// WebAssembly (raw-deflated, then base64: the view inflates it with the +// platform's DecompressionStream) and as the same build translated to +// JavaScript. The page // loads nothing and connects nowhere. The servers serve it for each of the six // views, naming the view in its . // @@ -17,6 +19,7 @@ // sources as they are: every source it names unchanged, and no source added. import { build, transform } from 'esbuild'; import { createHash } from 'node:crypto'; +import { deflateRawSync } from 'node:zlib'; import { mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'; import { dirname, join, relative } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -84,6 +87,9 @@ if (checking) { const engineJs = (await transform(readFileSync(jsPath, 'utf8'), { format: 'iife', globalName: '__wqEngine', minify: true, legalComments: 'none', target: 'es2022' })).code; const factory = `globalThis.wqEngineJs=function(){${engineJs};return __wqEngine};`; const wasm = readFileSync(wasmPath); +// Carried deflated (RFC 1951, zlib's best compression): less than half its +// bytes, and the page within its limit with the engine whole. +const wasmDeflated = deflateRawSync(wasm, { level: 9 }); const css = (await transform(styleFiles.map((f) => readFileSync(join(here, f), 'utf8')).join('\n'), { loader: 'css', minify: true, legalComments: 'none' })).code; // Text inside a + @@ -114,11 +120,11 @@ const manifest = { about: 'The page every view of WAI Quantum is served from, the view named in its . Built by wai/wai-quantum-views/build.sh; do not edit it by hand.', placeholder: PLACEHOLDER, limit_bytes: LIMIT, - bytes: { page: bytes(html), script: bytes(script), styles: bytes(css), engine_wasm: wasm.length, engine_wasm_base64: Math.ceil(wasm.length / 3) * 4, engine_js: bytes(factory) }, - sha256: { page: sha(html), script: sha(script), styles: sha(css), engine_wasm: sha(wasm), engine_js: sha(factory) }, + bytes: { page: bytes(html), script: bytes(script), styles: bytes(css), engine_wasm: wasm.length, engine_wasm_deflated: wasmDeflated.length, engine_wasm_base64: Math.ceil(wasmDeflated.length / 3) * 4, engine_js: bytes(factory) }, + sha256: { page: sha(html), script: sha(script), styles: sha(css), engine_wasm: sha(wasm), engine_wasm_deflated: sha(wasmDeflated), engine_js: sha(factory) }, sources: Object.fromEntries(sources.map((p) => [p, sha(readFileSync(join(repo, p)))])), }; mkdirSync(out, { recursive: true }); writeFileSync(join(out, 'wai-quantum-views.html'), html); writeFileSync(join(out, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n'); -console.log(`wrote ${join(out, 'wai-quantum-views.html')}: ${bytes(html)} bytes (script ${bytes(script)}, styles ${bytes(css)}, engine ${wasm.length} as WebAssembly and ${bytes(factory)} as JavaScript)`); +console.log(`wrote ${join(out, 'wai-quantum-views.html')}: ${bytes(html)} bytes (script ${bytes(script)}, styles ${bytes(css)}, engine ${wasm.length} as WebAssembly (${wasmDeflated.length} deflated) and ${bytes(factory)} as JavaScript)`); diff --git a/wai/quantum-studio/src/views/check.js b/wai/quantum-studio/src/views/check.js index 457eac798..0b0212da5 100644 --- a/wai/quantum-studio/src/views/check.js +++ b/wai/quantum-studio/src/views/check.js @@ -2,8 +2,9 @@ // on the machine that shows it, by the engine's own code. // // The page carries the engine twice, put in by the build: as WebAssembly -// (globalThis.WQ_ENGINE_WASM, base64) and as the same build translated to -// JavaScript (globalThis.wqEngineJs(), a factory). A host's content-security +// (globalThis.WQ_ENGINE_WASM, the module raw-deflated, RFC 1951, then base64) +// and as the same build translated to JavaScript (globalThis.wqEngineJs(), a +// factory). A host's content-security // policy may refuse to compile WebAssembly (the extension's default policy // has no 'wasm-unsafe-eval'); the page's own script runs wherever the view // does, so the second form checks the receipt there. Both give the same @@ -29,7 +30,11 @@ export function engine() { try { const b64 = globalThis.WQ_ENGINE_WASM; if (!b64) throw new Error('this page carries no WebAssembly engine'); - const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); + const deflated = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); + // Inflated here: the platform's own decompressor, no request and no code + // compiled from text, so a policy that refuses both lets it run. + const inflated = new Blob([deflated]).stream().pipeThrough(new DecompressionStream('deflate-raw')); + const bytes = await new Response(inflated).arrayBuffer(); const { instance } = await WebAssembly.instantiate(bytes, {}); return { form: 'WebAssembly', call: driver(instance.exports) }; } catch (e) { diff --git a/wai/registry/capabilities.json b/wai/registry/capabilities.json index 7f2fe5695..4e4cb9a3e 100644 --- a/wai/registry/capabilities.json +++ b/wai/registry/capabilities.json @@ -3183,6 +3183,10 @@ "label": "wai.quantum.phasor", "reason": "a module label: wai-quantum's `quantum_phasor` and `quantum_phasor_meter`, the phasor bridge and its energy-accounted receipts" }, + { + "label": "wai.quantum.planner/2", + "reason": "refused on purpose: a format of a contract job's reasoning that no text defines; the planner's test and the job receipts corpus seal it in a result to see the reasoning refused (quantum-providers §8.7)" + }, { "label": "wai.quantum.provider-job/1", "reason": "a document with no schema file: the record wai-quantum-qpu keeps of a job on a person's provider, written before the job is sent" @@ -3275,6 +3279,14 @@ "label": "wai.quantum.tdvp", "reason": "a module label: wai-quantum's `quantum_tdvp`, time evolution of spin chains by TDVP" }, + { + "label": "wai.quantum.timings/1", + "reason": "a document with no schema file: the runs the command line has timed and read the energy of on this machine, by method, that its estimate of a job's energy rests on (wai-quantum-cli's `estimates`)" + }, + { + "label": "wai.quantum.timings/9", + "reason": "refused on purpose: a major of the command line's timings that no text defines; its test writes it to see the file kept aside and a new one begun" + }, { "label": "wai.quantum.tn", "reason": "a module label: wai-quantum's `quantum_tn`, tensor-network contraction" diff --git a/wai/wai-quantum-cli/README.md b/wai/wai-quantum-cli/README.md index 978e6b92a..f3fcb6323 100644 --- a/wai/wai-quantum-cli/README.md +++ b/wai/wai-quantum-cli/README.md @@ -109,6 +109,8 @@ wai-quantum run circuit.qasm --method statevector --fabric cpu --fabric cpu --sh wai-quantum run prog.qasm --fabric a-member-elsewhere # exits 1 ``` +**Under a contract.** `--exactness CLASS`, `--deadline SECONDS`, `--max-cost 0.50:USD`, `--max-joules J` and `--allow-providers` (or `--contract` with the JSON of [the provider protocol's section 8.7](../extensions/quantum-providers.md)) say what the answer must be. The planner then prices every route it can see: each method here, at its memory and the time its work predicts, and with `--allow-providers` each of your own providers, by its own estimate and what that leaves out (each is asked, and sent nothing). It rejects every route that cannot meet the contract, runs the cheapest of the rest, and seals its reasoning in the receipt. An unknown never passes: a time nobody states does not meet a deadline, nor an unknown cost a ceiling, nor an estimate that is only the least a job can come to. Nothing falls back, from exact to approximate or between a simulator and a device, and with no route left the job is refused with every route's reason (`J071`). A contract that names no class keeps the class `auto` would give, and a device's counts are reached only by asking for `measured` (or `any`). A provider's answer carries a classical method's counts beside it, with their distance, wherever a method here can reach them in the time the contract leaves, and the receipt says why where none can. Under a contract no provider is asked anything without `--allow-providers` and a class one could give (`--exactness measured`, `simulated` or `any`), and one you name is refused without them (`J070`). A ceiling bounds the estimate a route is chosen by, not what is charged after, and confirms nothing: a run on a provider you name that is not free still takes `--yes`, and one the planner routes to a provider that is not free takes `--confirm WORD`, the word its `--dry-run` prints for that route, that provider and device, that estimate, that program and that contract, and is refused if any of them has changed when it would be sent; a word sends one run, and a dry run after it gives the word for the next. A deadline holds a method's own run time here, and a provider's from its submission to its counts; the command line cancels a provider's job still waiting at it (`J074`), and a job ends there only on the provider's word that it was cancelled: a provider that says it cannot cancel (the cloud-tasks kinds, or an open-protocol provider whose `describe` says `"cancels": false`) says so in its price, and its job stays waiting. A ceiling on energy is held by a live reading while the run goes: under `--max-joules` the run is a process of its own, which the command line reads about every ten milliseconds as the host schedules it (on macOS that process's CPU energy, on Linux the processor packages', where you may read them) and kills at the ceiling, so the work stops there; the run gives no answer, says so, seals a receipt that says so with what the run took in all and the longest time between two reads, and exits 4. A run that ends between two reads is read whole all the same, and one past its ceiling is sealed as having missed it and exits 4. A counter silent for a second stops the run too, and nothing is sealed. No figure before a run can promise what it will take, since a job's work leaves out what drives its time. So a route nothing here can read and stop is refused and says why (`energy_unwatched`): no counter that reads here, a method on a GPU or an accelerator no counter here reads, a provider, and every run from a server, from `mcp` or from anything else with other work in its process, which a ceiling could not stop alone. Beside each route is an estimate, from the power and the time of that method's last runs read here, labelled one: it can refuse a job clearly past the ceiling (`energy`), and it promises nothing under it. Around a `run` the command line reads when a ceiling asks or the method has fewer than three runs read, and keeps the reading only on this machine, under this build's version, profile and features, in `$WAI_QUANTUM_TIMINGS`, or `$XDG_CONFIG_HOME/wai/quantum-timings.json`, or `~/.config/wai/quantum-timings.json` (`WAI_QUANTUM_TIMINGS=off` keeps none). A run under a ceiling is read whole, in its own process, and that figure is sealed; a run without one is not, since a run read in the command line's own process is not read completely. `plan` and `run` show the estimate and what would read the run. `wai-quantum plan` with the same options shows every route's price or reason and sends nothing; `wai-quantum verify --recheck` prices the routes again here and runs the shadow again; a run that kept less than its contract asked is still sealed, says so, and exits 4. + Each result names: - its method, and why that method was chosen; @@ -456,7 +458,7 @@ It also serves the engine's resources and prompts, the same as the job service's ### Views in the agent's host -A host that draws interactive views (the protocol's extension `io.modelcontextprotocol/ui`, version 2026-01-26, said in the client's `initialize`) gets the engine's answers as views beside the conversation: a run's result with its verdict, a receipt, a circuit (a lint, a drawing, a repair, a compile with its certificate), a critique marked on its circuit, an estimate's frontier and a device target's map. Each tool that has one names it in `_meta.ui.resourceUri`, the six `ui://wai-quantum/*` resources are listed and read, and each answer carries what its view draws (the engine's layout, the circuit in words, a target's map) in its `_meta`, which the model does not read. The views are one self-contained page (`wai/wai-quantum/views/`, 802 KB, held under 1 MiB) that loads nothing and connects nowhere; it checks the receipt of what it shows with the engine inside it, as WebAssembly where the host's content-security policy allows it and translated to JavaScript where it does not (the extension's default policy refuses WebAssembly), and tells the model what it found. A host that draws no views is told nothing of them; every answer that has a view also comes in plain words beside its JSON. +A host that draws interactive views (the protocol's extension `io.modelcontextprotocol/ui`, version 2026-01-26, said in the client's `initialize`) gets the engine's answers as views beside the conversation: a run's result with its verdict, a receipt, a circuit (a lint, a drawing, a repair, a compile with its certificate), a critique marked on its circuit, an estimate's frontier and a device target's map. Each tool that has one names it in `_meta.ui.resourceUri`, the six `ui://wai-quantum/*` resources are listed and read, and each answer carries what its view draws (the engine's layout, the circuit in words, a target's map) in its `_meta`, which the model does not read. The views are one self-contained page (`wai/wai-quantum/views/`, 880 KB, held under 1 MiB) that loads nothing and connects nowhere; it checks the receipt of what it shows with the engine inside it, as WebAssembly where the host's content-security policy allows it and translated to JavaScript where it does not (the extension's default policy refuses WebAssembly), and tells the model what it found. A host that draws no views is told nothing of them; every answer that has a view also comes in plain words beside its JSON. ### Scoring a model diff --git a/wai/wai-quantum-cli/README.zh-CN.md b/wai/wai-quantum-cli/README.zh-CN.md index 5e5c9ba8a..901bb2d15 100644 --- a/wai/wai-quantum-cli/README.zh-CN.md +++ b/wai/wai-quantum-cli/README.zh-CN.md @@ -112,6 +112,8 @@ wai-quantum run circuit.qasm --method statevector --fabric cpu --fabric cpu --sh wai-quantum run prog.qasm --fabric a-member-elsewhere # exits 1:别处的成员,被拒绝 ``` +**在契约之下。** `--exactness CLASS`、`--deadline SECONDS`、`--max-cost 0.50:USD`、`--max-joules J` 和 `--allow-providers`(或用 `--contract` 给出 [提供方协议第 8.7 节](../extensions/quantum-providers.md) 的 JSON)说明答案必须满足什么。规划器随后为它能看到的每条路径定价:本机的每个方法,按其内存和其工作量所预示的时间;加上 `--allow-providers` 时,还有你自己的每个提供方,按其自身的估算以及该估算未包含的内容(每个都会被询问,但不会发送任何东西)。它拒绝每条无法满足契约的路径,运行其余路径中最便宜的一条,并把它的推理封入收据。未知量从不算作满足:无人说明的时间不满足截止时间,未知的费用不满足上限,只是作业最低可能费用的估算也不满足。不会回退:既不会从精确退到近似,也不会在模拟器与设备之间互换;没有路径剩下时,作业被拒绝,并列出每条路径的原因(`J071`)。未指明类别的契约保留 `auto` 会给出的类别;只有请求 `measured`(或 `any`)才会用到设备的计数。提供方的答案旁边附有经典方法的计数及两者的距离,只要本机有方法能在契约留下的时间内得到它们;没有方法能做到时,收据会说明原因。在契约之下,没有 `--allow-providers` 以及提供方能够给出的类别(`--exactness measured`、`simulated` 或 `any`)时,不会询问任何提供方,你指定的提供方也会被拒绝(`J070`)。上限约束的是选择路径所依据的估算,而不是之后实际收取的费用,它也不构成确认:在你指定的提供方上运行、且不免费时,仍需要 `--yes`;规划器选到的提供方不免费时,需要 `--confirm WORD`,即它的 `--dry-run` 为该路径、该提供方和设备、该估算、该程序和该契约打印的词,一个词只发送一次运行,之后的预演会给出下一次运行的词,发送时只要其中任何一项已有变化就会被拒绝。截止时间约束本机方法自身的运行时间,以及提供方从提交到得出计数的时间;命令行会在截止时取消仍在等待的提供方作业(`J074`),且只有提供方确认已取消时作业才在此结束:声明无法取消的提供方(cloud-tasks 各类,或 `describe` 中写明 `"cancels": false` 的开放协议提供方)会在其价格中说明,其作业继续等待。能量上限由运行期间的实时读数来保证:在 `--max-joules` 之下,运行在独立的进程中进行,命令行大约每十毫秒(视主机调度而定)读取一次(macOS 上是该进程的 CPU 能量,Linux 上是你有权读取的处理器封装计数器),达到上限时立即终止该进程,工作随即停止;运行不给出答案,如实说明,封存一份说明此事的收据,其中写明运行总共耗用的能量以及两次读取之间的最长间隔,并以状态 4 退出。在两次读取之间结束的运行同样会被完整读取,超过上限的会被封存为未满足上限,并以状态 4 退出。计数器沉默一秒时运行同样被停止,且不封存任何内容。运行之前的任何数字都无法保证它实际的能耗,因为作业的工作量并不包含决定其时间的全部因素。因此,本机无法读取并停止的路径会被拒绝并说明原因(`energy_unwatched`):此处没有可读的计数器、方法运行在此处没有计数器读取的 GPU 或加速器上、提供方,以及来自服务器、`mcp` 或其进程中还有其他工作的任何运行,上限无法单独停止它们。每条路径旁边有一个估算,来自该方法在本机最近读取过的运行的功率和时间,并标明是估算:它可以拒绝明显超过上限的作业(`energy`),但不对上限以下作任何保证。当有上限要求,或该方法读取过的运行少于三次时,命令行会在 `run` 前后读取,读数只保存在本机,按此构建的版本、配置和特性区分,存于 `$WAI_QUANTUM_TIMINGS`、`$XDG_CONFIG_HOME/wai/quantum-timings.json` 或 `~/.config/wai/quantum-timings.json` 中(`WAI_QUANTUM_TIMINGS=off` 表示不保存)。在上限之下的运行在其独立进程中被完整读取,该数字会被封存;没有上限的运行则不封存,因为在命令行自身进程内读取的运行读不完整。`plan` 和 `run` 会显示估算以及将由什么读取这次运行。带相同选项的 `wai-quantum plan` 显示每条路径的价格或原因,不发送任何东西;`wai-quantum verify --recheck` 在本机重新为路径定价并重新运行影子运行;未能满足契约全部要求的运行仍会被封存,并如实说明,退出状态为 4。 + 每个结果都注明: - 所用的方法,以及选择该方法的原因; diff --git a/wai/wai-quantum-cli/docs/llms-full.txt b/wai/wai-quantum-cli/docs/llms-full.txt index 4adebe58f..259628a97 100644 --- a/wai/wai-quantum-cli/docs/llms-full.txt +++ b/wai/wai-quantum-cli/docs/llms-full.txt @@ -28,7 +28,7 @@ Generated by `wai-quantum docs llms` from the tool lists both MCP servers serve, ## Receipts -Every result carries an Ed25519 signature over the BLAKE3 digest of the RFC 8785 canonical text of the request and of the result without its receipt. The job service signs with the key `GET /v1` publishes; the command line signs with the user's own key (`wai-quantum key` prints its did:key). `wai-quantum verify` checks either offline, and a result still verifies after any JSON reader has carried it. A receipt shows that the key signed this request and this result, and anyone can rerun the request to compare; it does not show who holds the key, nor that the physics is right. A result's `energy` is the CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or `unmetered` with the reason (the command line does not meter a run). +Every result carries an Ed25519 signature over the BLAKE3 digest of the RFC 8785 canonical text of the request and of the result without its receipt. The job service signs with the key `GET /v1` publishes; the command line signs with the user's own key (`wai-quantum key` prints its did:key). `wai-quantum verify` checks either offline, and a result still verifies after any JSON reader has carried it. A receipt shows that the key signed this request and this result, and anyone can rerun the request to compare; it does not show who holds the key, nor that the physics is right. A result's `energy` is the CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or `unmetered` with the reason (the command line seals no reading of a run: it reads some runs only to bound later ones). ## Versions and stability @@ -43,7 +43,7 @@ Runs on this machine, signed with the user's key; nothing leaves the machine. ### `run_quantum_circuit`: Run a quantum program here -Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more. +Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `contract` (the class wanted, a deadline) and the planner prices every method here, runs the cheapest that meets it, seals its reasoning under `planner`, and refuses (J071) rather than fall back to less; this tool reaches no provider, and plan_routes and run_routed do. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more. Parameters: - `source` (object): The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source. @@ -64,10 +64,11 @@ Parameters: - `mitigate` (any): Mitigate the job's expectation values (or, for readout, its counts) under its own noise: zne (the whole program folded U(U†U)^k and extrapolated), pea (the noise learned as a sparse Pauli–Lindblad model and amplified), pec (the learned channels inverted and sampled), cdr (a line fitted over near-Clifford training circuits), vd (two copies), readout (the counts' flips inverted). Needs noise and observables (shots for readout), at most 8 qubits. The result's `mitigation` gives raw and mitigated values with standard errors, the ideal value (known because this is a simulation), the method's bias and variance assumptions and its cost. A method's name, or an object. - `pulse` (object): A pulse run's options (method "pulse"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0. - `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050). +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). ### `plan_quantum_circuit`: Plan a quantum program -The method a program would run on and why, the memory and work it would take, without running it. +The method a program would run on and why, the memory and work it would take, without running it. With a contract, every route's price or reason for rejection under planner, or the refusal (J071) when no route meets it. Parameters: - `source` (object): The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source. @@ -88,6 +89,7 @@ Parameters: - `mitigate` (any): Mitigate the job's expectation values (or, for readout, its counts) under its own noise: zne (the whole program folded U(U†U)^k and extrapolated), pea (the noise learned as a sparse Pauli–Lindblad model and amplified), pec (the learned channels inverted and sampled), cdr (a line fitted over near-Clifford training circuits), vd (two copies), readout (the counts' flips inverted). Needs noise and observables (shots for readout), at most 8 qubits. The result's `mitigation` gives raw and mitigated values with standard errors, the ideal value (known because this is a simulation), the method's bias and variance assumptions and its cost. A method's name, or an object. - `pulse` (object): A pulse run's options (method "pulse"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0. - `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050). +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). ### `lint_qasm`: Check an OpenQASM program @@ -225,10 +227,11 @@ Parameters: ### `verify_quantum_result`: Check a result's receipt -Whether a job's receipt seals its request and its result, as run_quantum_circuit or the job service returns them, and every rule of its form holds (`reasons` names what does not), and which key signed it. +Whether a job's receipt seals its request and its result, as run_quantum_circuit or the job service returns them, and every rule of its form holds (`reasons` names what does not), and which key signed it; for a job under a contract, every route's outcome and the choice recomputed from what it states, and with recheck its routes priced again and its shadow run again. Parameters: - `job` (any, required): The job's text as it was given (preferred: read as the protocol reads it, so a member named twice or a number past what a parsed job keeps is seen), or the job: {"request": ..., "result": ...}, the result carrying its receipt. +- `recheck` (boolean): For a job under a contract: its routes priced again at the job's memory, held to the digest it sealed, and its shadow run again, held to its counts bit for bit. ### `discover_evaluate`: Judge a generator against a workbench specification @@ -441,6 +444,7 @@ Parameters: - `mitigate` (any): Mitigate the job's expectation values (or, for readout, its counts) under its own noise: zne (the whole program folded U(U†U)^k and extrapolated), pea (the noise learned as a sparse Pauli–Lindblad model and amplified), pec (the learned channels inverted and sampled), cdr (a line fitted over near-Clifford training circuits), vd (two copies), readout (the counts' flips inverted). Needs noise and observables (shots for readout), at most 8 qubits. The result's `mitigation` gives raw and mitigated values with standard errors, the ideal value (known because this is a simulation), the method's bias and variance assumptions and its cost. A method's name, or an object. - `pulse` (object): A pulse run's options (method "pulse"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0. - `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050). +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). ### `qec_code`: Show an error-correcting code and certify its distance @@ -586,6 +590,7 @@ Parameters: - `inputs` (object): A generator's inputs' values, as {"n": 5}. - `shots` (integer): Shots (default 1024). - `seed` (integer): A seed, for a provider that is a seeded simulator; a device ignores it. +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). ### `run_on_provider`: Run on a provider (can spend the person's money) @@ -597,8 +602,34 @@ Parameters: - `inputs` (object): A generator's inputs' values, as {"n": 5}. - `shots` (integer): Shots (default 1024). - `seed` (integer): A seed, for a provider that is a seeded simulator; a device ignores it. +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). - `confirm_cost` (boolean): true only when the person has agreed to this run's cost. A run that is not free is refused without it. +### `plan_routes`: Weigh a contract against every route + +Every route a job could take under its contract: the methods on this machine and each of the person's own providers, each with its price or why it was rejected, what a provider's estimate leaves out, and the route the planner would choose: the cheapest that meets the contract, or the refusal (J071) with every route's reason. Each provider is asked to describe its device and estimate the job. Nothing is submitted and nothing is spent. A device is chosen only when exactness asks for measured or any. + +Parameters: +- `qasm` (string, required): The program, OpenQASM 3. A provider takes one whose measurements all come at the end and whose every angle is a dyadic multiple of 2π; one it cannot take is a route with why. +- `inputs` (object): A generator's inputs' values, as {"n": 5}. +- `shots` (integer): Shots (default 1024). +- `seed` (integer): A seed. +- `observables` (array): Pauli observables: a provider's job answers counts, so a method here answers these. +- `contract` (any, required): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). + +### `run_routed`: Run a job on the route its contract chooses (can spend the person's money) + +Runs a job on the route plan_routes chooses: a method on this machine, or one of the person's own providers. THIS CAN SPEND THE PERSON'S MONEY OR QUOTA, when the contract allows a provider and one is chosen. A cost ceiling confirms nothing: a run that is not free is refused unless confirm is the word plan_routes gave for that route, its estimate and its program (its confirm.token), set only after the person has seen them and agreed to that run; if the route or its estimate changed since, it is refused with the new word. The answer is a job in the service's form, its result carrying the planner's reasoning under planner; a provider's result also carries a classical method's counts and their distance under shadow, or why no classical method could reach them. If the job has not finished within this call the answer has status running and an id, and get_provider_job collects it later. Do not run it again to find out: that is a second job, and it can be a second bill. + +Parameters: +- `qasm` (string, required): The program, OpenQASM 3. A provider takes one whose measurements all come at the end and whose every angle is a dyadic multiple of 2π; one it cannot take is a route with why. +- `inputs` (object): A generator's inputs' values, as {"n": 5}. +- `shots` (integer): Shots (default 1024). +- `seed` (integer): A seed. +- `observables` (array): Pauli observables: a provider's job answers counts, so a method here answers these. +- `contract` (any, required): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). +- `confirm` (string): The word plan_routes gave (confirm.token) for the route, the estimate and the program the person agreed to. A run that is not free is refused without it, whatever the contract's ceiling, and refused if what is chosen now is not what that word names. + ### `get_provider_job`: Ask after a job on a provider Where a job on one of the person's providers stands, by the id run_on_provider gave: still running, or finished, with its counts then sealed in a receipt, or ended, with why. Asking spends nothing and can be repeated; a finished job gives the same answer every time. It asks once and does not wait, so ask again later rather than in a loop: a device's queue can take hours or days. @@ -643,6 +674,7 @@ Parameters: - `pulse` (object): A pulse run's options (method "pulse"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0. - `source` (object): The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source. - `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes. +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). - `idempotency_key` (string): A key of your making that names this run, so that a call sent again is not a second job: the same key with the same arguments answers with the job it names, for as long as the job is kept, rather than running another; the same key with other arguments is refused (J034). Make it unguessable (a UUID). A job the service interrupted is run again under its key. Without a key, every call is a new job. ### `run_quantum_set`: Run a set of quantum programs, or one over a grid @@ -694,6 +726,7 @@ Parameters: - `programs` (array): The set's programs: each a program's text, or a job ({"qasm", …}) whose own fields win over the set's. - `sweep` (object): Each input of qasm and its values: every combination runs, the names in sorted order, the first varying slowest; an integer input's values are whole numbers. - `source` (object): The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source. +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). ### `get_quantum_job`: Read a quantum job @@ -828,7 +861,7 @@ Parameters: - `observables` (array): Pauli strings to take expectation values of, e.g. ["Z0", "Z0 Z1", "X2 Y3"]. Qubits count from 0. - `amplitudes` (array): Basis states to give amplitudes of: one character per qubit, qubit n-1 first, e.g. "0011". - `noise` (object): Optional noise, each a probability: depolarizing_1q, depolarizing_2q, amplitude_damping, dephasing (after each gate on its qubits), readout (each measured bit). -- `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes. +- `contract` (any): What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073). - `seed` (integer): Sampling seed (default 1); the same job and seed give the same counts. - `options` (object): Advanced, per method: max_bond (mps), threshold and max_terms (pauli), fusion (statevector), controls (statevector and exact), trajectories. - `compile` (object): Compile the program first (as compile_qasm does) and run the compiled circuit: with basis clifford_t it runs bit-exact, and the result's `compiled` states its distance from the program. @@ -839,6 +872,7 @@ Parameters: - `mitigate` (any): Mitigate the job's expectation values (or, for readout, its counts) under its own noise: zne (the whole program folded U(U†U)^k and extrapolated), pea (the noise learned as a sparse Pauli–Lindblad model and amplified), pec (the learned channels inverted and sampled), cdr (a line fitted over near-Clifford training circuits), vd (two copies), readout (the counts' flips inverted). Needs noise and observables (shots for readout), at most 8 qubits. The result's `mitigation` gives raw and mitigated values with standard errors, the ideal value (known because this is a simulation), the method's bias and variance assumptions and its cost. A method's name, or an object. - `pulse` (object): A pulse run's options (method "pulse"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0. - `source` (object): The program in another format, in place of qasm: read to the job's qasm before the job is read (a module that does not read is refused with the reader's code, Q700 to Q721), the request keeping its source. +- `params` (object): A value for each of the program's parameters (input float theta;, input angle phi;), as {"theta": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes. - `idempotency_key` (string): A key of your making that names this run, so that a call sent again is not a second job: the same key with the same arguments answers with the job it names, for as long as the job is kept, rather than running another; the same key with other arguments is refused (J034). Make it unguessable (a UUID). A job the service interrupted is run again under its key. Without a key, every call is a new job. ### `quantum_circuit_examples`: Ready-to-run quantum examples @@ -1844,6 +1878,37 @@ Options: them. A member certified bit-exact gives the CPU's answers; a placement this host cannot honour is refused (J013) + --exactness + The class the answer must be of: bit-exact, exact, single, bounded, estimate, heuristic; + measured (a processor's counts), simulated (a provider's simulator's), or any. Under a + contract (this, --max-cost, --deadline, --max-joules or --allow-providers) the planner + prices every route it can see, runs the cheapest that meets it, and seals its reasoning in + the receipt; with nothing to meet it, it refuses with each route's reason (J071), and + nothing falls back. Without a class the job keeps the class auto would give + + --max-cost + The most the run may cost, as 0.50:USD: a route with an unknown cost, or priced in another + currency, does not meet it. It confirms nothing: a run that is not free still takes --yes + + --deadline + When the run must be done by, in seconds: a route whose time is not known does not meet + it, and the receipt says whether it was kept (exit 4 when it was not) + + --max-joules + The most energy the run may take, in joules, held by a live reading while it runs: at the + ceiling it is stopped, and the receipt says so. A route nothing can read or stop is + refused; an estimate beside it promises nothing + + --allow-providers + Let the planner weigh your own providers (`wai-quantum providers list`) beside the methods + here: each is asked to estimate the job, and nothing is sent unless one is chosen. A + device is chosen only when --exactness measured or any asks for its class. On the job + service, which reaches no provider, it changes nothing + + --contract + The contract itself, as JSON or a file of it: exactness, max_cost, deadline_seconds, + max_joules and providers; the options above are set over it + --json Print the job as the service returns it: request, plan, result and receipt @@ -1865,16 +1930,22 @@ Options: simulator --dry-run - With --provider: the plan (the exact compile to the device's gates and its check by - simulation) and the provider's estimate; nothing is submitted + With --provider or --allow-providers: the plan (the exact compile to the device's gates + and its check by simulation) and the provider's estimate, or every route's price or + reason; nothing is submitted --yes - With --provider: confirm a run that is not free, or whose cost is unknown; without it such - a run is refused (exit 3) + With --provider or --allow-providers: confirm a run that is not free, or whose cost is + unknown; without it such a run is refused (exit 3). A cost ceiling is no confirmation --no-wait - With --provider: send the job and answer with its handle, without waiting (`wai-quantum - providers collect`) + With --provider or --allow-providers: send the job and answer with its handle, without + waiting (`wai-quantum providers collect`) + + --confirm + With --allow-providers: confirm the run the planner chose when it is not free, by the word + its dry run gave for that route, its estimate and its program; a route, an estimate or a + program that changed since is refused. --yes confirms only a provider you name -h, --help Print help @@ -1998,6 +2069,37 @@ Options: them. A member certified bit-exact gives the CPU's answers; a placement this host cannot honour is refused (J013) + --exactness + The class the answer must be of: bit-exact, exact, single, bounded, estimate, heuristic; + measured (a processor's counts), simulated (a provider's simulator's), or any. Under a + contract (this, --max-cost, --deadline, --max-joules or --allow-providers) the planner + prices every route it can see, runs the cheapest that meets it, and seals its reasoning in + the receipt; with nothing to meet it, it refuses with each route's reason (J071), and + nothing falls back. Without a class the job keeps the class auto would give + + --max-cost + The most the run may cost, as 0.50:USD: a route with an unknown cost, or priced in another + currency, does not meet it. It confirms nothing: a run that is not free still takes --yes + + --deadline + When the run must be done by, in seconds: a route whose time is not known does not meet + it, and the receipt says whether it was kept (exit 4 when it was not) + + --max-joules + The most energy the run may take, in joules, held by a live reading while it runs: at the + ceiling it is stopped, and the receipt says so. A route nothing can read or stop is + refused; an estimate beside it promises nothing + + --allow-providers + Let the planner weigh your own providers (`wai-quantum providers list`) beside the methods + here: each is asked to estimate the job, and nothing is sent unless one is chosen. A + device is chosen only when --exactness measured or any asks for its class. On the job + service, which reaches no provider, it changes nothing + + --contract + The contract itself, as JSON or a file of it: exactness, max_cost, deadline_seconds, + max_joules and providers; the options above are set over it + --json Print the plan as JSON @@ -3100,6 +3202,37 @@ Options: them. A member certified bit-exact gives the CPU's answers; a placement this host cannot honour is refused (J013) + --exactness + The class the answer must be of: bit-exact, exact, single, bounded, estimate, heuristic; + measured (a processor's counts), simulated (a provider's simulator's), or any. Under a + contract (this, --max-cost, --deadline, --max-joules or --allow-providers) the planner + prices every route it can see, runs the cheapest that meets it, and seals its reasoning in + the receipt; with nothing to meet it, it refuses with each route's reason (J071), and + nothing falls back. Without a class the job keeps the class auto would give + + --max-cost + The most the run may cost, as 0.50:USD: a route with an unknown cost, or priced in another + currency, does not meet it. It confirms nothing: a run that is not free still takes --yes + + --deadline + When the run must be done by, in seconds: a route whose time is not known does not meet + it, and the receipt says whether it was kept (exit 4 when it was not) + + --max-joules + The most energy the run may take, in joules, held by a live reading while it runs: at the + ceiling it is stopped, and the receipt says so. A route nothing can read or stop is + refused; an estimate beside it promises nothing + + --allow-providers + Let the planner weigh your own providers (`wai-quantum providers list`) beside the methods + here: each is asked to estimate the job, and nothing is sent unless one is chosen. A + device is chosen only when --exactness measured or any asks for its class. On the job + service, which reaches no provider, it changes nothing + + --contract + The contract itself, as JSON or a file of it: exactness, max_cost, deadline_seconds, + max_joules and providers; the options above are set over it + --json Print the job as the service returns it: request, plan, result and receipt @@ -3604,6 +3737,10 @@ Options: One job a line, each judged as a job's receipt, one JSON verdict a line; the status is 1 when any is not valid + --recheck + For a job under a contract, also run again what can be: its routes priced again at the + job's memory, held to the digest it sealed, and its shadow, held to its counts bit for bit + -h, --help Print help diff --git a/wai/wai-quantum-cli/docs/llms.txt b/wai/wai-quantum-cli/docs/llms.txt index 4992acc46..d58cbf25a 100644 --- a/wai/wai-quantum-cli/docs/llms.txt +++ b/wai/wai-quantum-cli/docs/llms.txt @@ -28,7 +28,7 @@ Generated by `wai-quantum docs llms` from the tool lists both MCP servers serve, ## Receipts -Every result carries an Ed25519 signature over the BLAKE3 digest of the RFC 8785 canonical text of the request and of the result without its receipt. The job service signs with the key `GET /v1` publishes; the command line signs with the user's own key (`wai-quantum key` prints its did:key). `wai-quantum verify` checks either offline, and a result still verifies after any JSON reader has carried it. A receipt shows that the key signed this request and this result, and anyone can rerun the request to compare; it does not show who holds the key, nor that the physics is right. A result's `energy` is the CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or `unmetered` with the reason (the command line does not meter a run). +Every result carries an Ed25519 signature over the BLAKE3 digest of the RFC 8785 canonical text of the request and of the result without its receipt. The job service signs with the key `GET /v1` publishes; the command line signs with the user's own key (`wai-quantum key` prints its did:key). `wai-quantum verify` checks either offline, and a result still verifies after any JSON reader has carried it. A receipt shows that the key signed this request and this result, and anyone can rerun the request to compare; it does not show who holds the key, nor that the physics is right. A result's `energy` is the CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or `unmetered` with the reason (the command line seals no reading of a run: it reads some runs only to bound later ones). ## Versions and stability @@ -92,6 +92,8 @@ Runs on this machine, signed with the user's key; nothing leaves the machine. - `providers_list`: List the person's quantum providers - `provider_estimate`: Plan a run on a provider, and its cost - `run_on_provider`: Run on a provider (can spend the person's money) +- `plan_routes`: Weigh a contract against every route +- `run_routed`: Run a job on the route its contract chooses (can spend the person's money) - `get_provider_job`: Ask after a job on a provider - `cancel_provider_job`: Cancel a job on a provider - `list_provider_jobs`: List the jobs on the person's providers diff --git a/wai/wai-quantum-cli/docs/local-mcp.json b/wai/wai-quantum-cli/docs/local-mcp.json index 08198bceb..1436697ec 100644 --- a/wai/wai-quantum-cli/docs/local-mcp.json +++ b/wai/wai-quantum-cli/docs/local-mcp.json @@ -4,7 +4,7 @@ { "name": "run_quantum_circuit", "title": "Run a quantum program here", - "description": "Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more.", + "description": "Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `contract` (the class wanted, a deadline) and the planner prices every method here, runs the cheapest that meets it, seals its reasoning under `planner`, and refuses (J071) rather than fall back to less; this tool reaches no provider, and plan_routes and run_routed do. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more.", "inputSchema": { "type": "object", "anyOf": [ @@ -531,6 +531,78 @@ "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050)." + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -1358,6 +1430,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -1476,9 +1620,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -4194,6 +4339,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -5204,6 +6327,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -5320,9 +6515,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -8038,6 +9234,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -8898,7 +11072,7 @@ { "name": "plan_quantum_circuit", "title": "Plan a quantum program", - "description": "The method a program would run on and why, the memory and work it would take, without running it.", + "description": "The method a program would run on and why, the memory and work it would take, without running it. With a contract, every route's price or reason for rejection under planner, or the refusal (J071) when no route meets it.", "inputSchema": { "type": "object", "anyOf": [ @@ -9425,17 +11599,89 @@ "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050)." + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, "outputSchema": { "$id": "wai-quantum://schemas/plan_quantum_circuit/1", "type": "object", - "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it.", + "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it. A job with a contract carries the planner's reasoning.", "anyOf": [ { "title": "wai.quantum.plan/1", - "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it.", + "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it. A job with a contract carries the planner's reasoning.", "type": "object", "required": [ "method", @@ -9513,6 +11759,677 @@ } } }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, "metered": { "type": "boolean", "description": "True when a job naming method mps would pass one job's work at the bond it asks for: it runs under a meter of the bonds it reaches, may take far less than `work`, and stops with J011 if it passes `work`." @@ -21667,7 +24584,7 @@ { "name": "verify_quantum_result", "title": "Check a result's receipt", - "description": "Whether a job's receipt seals its request and its result, as run_quantum_circuit or the job service returns them, and every rule of its form holds (`reasons` names what does not), and which key signed it.", + "description": "Whether a job's receipt seals its request and its result, as run_quantum_circuit or the job service returns them, and every rule of its form holds (`reasons` names what does not), and which key signed it; for a job under a contract, every route's outcome and the choice recomputed from what it states, and with recheck its routes priced again and its shadow run again.", "inputSchema": { "type": "object", "required": [ @@ -21680,6 +24597,10 @@ "string" ], "description": "The job's text as it was given (preferred: read as the protocol reads it, so a member named twice or a number past what a parsed job keeps is seen), or the job: {\"request\": ..., \"result\": ...}, the result carrying its receipt." + }, + "recheck": { + "type": "boolean", + "description": "For a job under a contract: its routes priced again at the job's memory, held to the digest it sealed, and its shadow run again, held to its counts bit for bit." } } }, @@ -21733,6 +24654,28 @@ "null" ], "description": "That key as a did:key." + }, + "planner": { + "type": "object", + "description": "For a job under a contract, what its reasoning says: the route chosen, the class wanted and given, whether the choice depends on the host, what was kept, and the shadow." + }, + "recheck": { + "type": "object", + "description": "With recheck: whether the routes priced again and the shadow run again are what the job sealed.", + "properties": { + "holds": { + "type": "boolean" + }, + "engine": { + "type": "object" + }, + "priced": { + "type": "object" + }, + "shadow": { + "type": "object" + } + } } } }, @@ -30994,6 +33937,78 @@ "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050)." + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } }, "required": [ @@ -31824,6 +34839,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -31942,9 +35029,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -34660,6 +37748,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -35670,6 +39736,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -35786,9 +39924,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -38504,6 +42643,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -50908,6 +56025,78 @@ "type": "integer", "minimum": 0, "description": "A seed, for a provider that is a seeded simulator; a device ignores it." + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -50955,6 +56144,677 @@ "confirm": { "type": "string", "description": "What the person reads before confirming a run that is not free." + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } } } }, @@ -51040,6 +56900,78 @@ "minimum": 0, "description": "A seed, for a provider that is a seeded simulator; a device ignores it." }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } + }, "confirm_cost": { "type": "boolean", "description": "true only when the person has agreed to this run's cost. A run that is not free is refused without it." @@ -51873,6 +57805,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -51991,9 +57995,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -54709,6 +60714,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -55719,6 +62702,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -55835,9 +62890,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -58553,6 +65609,13173 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + }, + "error": { + "type": "string" + }, + "code": { + "type": "string", + "description": "A failed item's refusal code (engine::refusal)." + }, + "path": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The item's leaf's sibling digests up to the root, in hex." + } + } + } + } + } + } + ] + }, + "error": { + "type": "string", + "description": "Why a job failed, or why it was interrupted." + }, + "interruptions": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "The job service: each time it stopped while the job ran, in milliseconds since 1970. A job that was running when the service stopped is queued again, once, to run from its stored request." + }, + "submitted_ms": { + "type": "integer", + "description": "The job service: when it was submitted, in milliseconds since 1970." + }, + "started_ms": { + "type": "integer" + }, + "finished_ms": { + "type": "integer" + }, + "peak_rss_bytes": { + "type": "integer", + "description": "The job service: the most memory the job's process held." + }, + "digests": { + "type": "object", + "description": "The job service: the BLAKE3 digests its store keeps the job's objects under (the request, each program, the result and the receipt).", + "properties": { + "algorithm": { + "const": "blake3" + }, + "request": { + "type": [ + "string", + "null" + ] + }, + "programs": { + "type": "array", + "items": { + "type": "string" + } + }, + "result": { + "type": "string" + }, + "receipt": { + "type": "string" + } + } + } + } + }, + { + "type": "object", + "description": "A refusal as data: the message, every code in it (the last is the code), its outcome and meaning as the code's table gives them. A host that refuses for its own reasons gives the error alone.", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + }, + "message": { + "type": "string" + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "codes": { + "type": "array", + "items": { + "type": "string" + } + }, + "outcome": { + "enum": [ + "refused", + "retry", + "failed", + "lowered", + "carried", + "preserved", + "warned", + "dropped", + "defaulted" + ] + }, + "meaning": { + "type": "string" + } + } + } + ] + } + }, + { + "name": "plan_routes", + "title": "Weigh a contract against every route", + "description": "Every route a job could take under its contract: the methods on this machine and each of the person's own providers, each with its price or why it was rejected, what a provider's estimate leaves out, and the route the planner would choose: the cheapest that meets the contract, or the refusal (J071) with every route's reason. Each provider is asked to describe its device and estimate the job. Nothing is submitted and nothing is spent. A device is chosen only when exactness asks for measured or any.", + "inputSchema": { + "type": "object", + "required": [ + "qasm", + "contract" + ], + "properties": { + "qasm": { + "type": "string", + "description": "The program, OpenQASM 3. A provider takes one whose measurements all come at the end and whose every angle is a dyadic multiple of 2π; one it cannot take is a route with why." + }, + "inputs": { + "type": "object", + "additionalProperties": { + "type": "integer" + }, + "description": "A generator's inputs' values, as {\"n\": 5}." + }, + "shots": { + "type": "integer", + "minimum": 1, + "description": "Shots (default 1024)." + }, + "seed": { + "type": "integer", + "minimum": 0, + "description": "A seed." + }, + "observables": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Pauli observables: a provider's job answers counts, so a method here answers these." + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } + } + } + }, + "outputSchema": { + "$id": "wai-quantum://schemas/plan_routes/1", + "type": "object", + "description": "Every route a job could take under its contract, each with its price or why it was rejected, and the route chosen: nothing submitted, nothing spent.", + "anyOf": [ + { + "type": "object", + "description": "Every route a job could take under its contract, each with its price or why it was rejected, and the route chosen: nothing submitted, nothing spent.", + "required": [ + "dry_run", + "planner" + ], + "properties": { + "dry_run": { + "const": true + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "plan": { + "title": "wai.quantum.plan/1", + "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it. A job with a contract carries the planner's reasoning.", + "type": "object", + "required": [ + "method", + "why", + "memory_bytes", + "work", + "qubits" + ], + "properties": { + "method": { + "type": "string" + }, + "why": { + "type": "string" + }, + "memory_bytes": { + "type": "integer", + "minimum": 0 + }, + "work": { + "type": "integer", + "minimum": 0, + "description": "The method's own unit: an upper bound on what the run takes where the method's cost is known beforehand, and with `metered` what the meter holds it to." + }, + "qubits": { + "type": "integer", + "minimum": 0 + }, + "target": { + "type": "object", + "description": "A run on a device target: which target (its hash, as its receipt binds it), its calibration snapshot, where the program was placed and why, and the noise derived from the target.", + "required": [ + "name", + "hash" + ], + "properties": { + "name": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "hash_is": { + "type": "string" + }, + "calibration": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + } + }, + "source": { + "type": "object", + "properties": { + "format": { + "type": "string" + }, + "note": { + "type": "string" + } + } + }, + "placement": { + "type": "object", + "description": "The native gate set, the layout and routes chosen, the swaps, the expected success beside the fewest-swaps layout's, and the check of the compiled program." + }, + "noise": { + "type": "object", + "description": "The noise model derived from the target's calibration: its channels, durations and idling, and each qubit's readout." + } + } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "metered": { + "type": "boolean", + "description": "True when a job naming method mps would pass one job's work at the bond it asks for: it runs under a meter of the bonds it reaches, may take far less than `work`, and stops with J011 if it passes `work`." + } + } + }, + "provider_plan": { + "type": "object", + "description": "The dry run of a job on a provider: nothing submitted, nothing spent.", + "required": [ + "dry_run", + "provider", + "plan", + "estimate", + "free", + "confirm" + ], + "properties": { + "dry_run": { + "const": true + }, + "provider": { + "type": "object" + }, + "calibration": { + "type": [ + "string", + "null" + ] + }, + "billing": { + "type": "object" + }, + "plan": { + "type": "object" + }, + "estimate": { + "type": "object" + }, + "free": { + "type": "boolean" + }, + "confirm": { + "type": "string", + "description": "What the person reads before confirming a run that is not free." + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + } + } + }, + "confirm": { + "type": "object", + "description": "Where the route chosen is a provider's and not free: what a person confirms it by. token is a digest of the route, its estimate's money and the program and shots it would send; a run is sent only when given that token made again at send time.", + "required": [ + "token", + "route", + "money", + "says" + ], + "properties": { + "token": { + "type": "string" + }, + "route": { + "type": "string" + }, + "money": { + "type": "object" + }, + "says": { + "type": "string" + } + } + } + } + }, + { + "type": "object", + "description": "A refusal as data: the message, every code in it (the last is the code), its outcome and meaning as the code's table gives them. A host that refuses for its own reasons gives the error alone.", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "string" + }, + "message": { + "type": "string" + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "codes": { + "type": "array", + "items": { + "type": "string" + } + }, + "outcome": { + "enum": [ + "refused", + "retry", + "failed", + "lowered", + "carried", + "preserved", + "warned", + "dropped", + "defaulted" + ] + }, + "meaning": { + "type": "string" + } + } + } + ] + } + }, + { + "name": "run_routed", + "title": "Run a job on the route its contract chooses (can spend the person's money)", + "description": "Runs a job on the route plan_routes chooses: a method on this machine, or one of the person's own providers. THIS CAN SPEND THE PERSON'S MONEY OR QUOTA, when the contract allows a provider and one is chosen. A cost ceiling confirms nothing: a run that is not free is refused unless confirm is the word plan_routes gave for that route, its estimate and its program (its confirm.token), set only after the person has seen them and agreed to that run; if the route or its estimate changed since, it is refused with the new word. The answer is a job in the service's form, its result carrying the planner's reasoning under planner; a provider's result also carries a classical method's counts and their distance under shadow, or why no classical method could reach them. If the job has not finished within this call the answer has status running and an id, and get_provider_job collects it later. Do not run it again to find out: that is a second job, and it can be a second bill.", + "inputSchema": { + "type": "object", + "required": [ + "qasm", + "contract" + ], + "properties": { + "qasm": { + "type": "string", + "description": "The program, OpenQASM 3. A provider takes one whose measurements all come at the end and whose every angle is a dyadic multiple of 2π; one it cannot take is a route with why." + }, + "inputs": { + "type": "object", + "additionalProperties": { + "type": "integer" + }, + "description": "A generator's inputs' values, as {\"n\": 5}." + }, + "shots": { + "type": "integer", + "minimum": 1, + "description": "Shots (default 1024)." + }, + "seed": { + "type": "integer", + "minimum": 0, + "description": "A seed." + }, + "observables": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Pauli observables: a provider's job answers counts, so a method here answers these." + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } + }, + "confirm": { + "type": "string", + "description": "The word plan_routes gave (confirm.token) for the route, the estimate and the program the person agreed to. A run that is not free is refused without it, whatever the contract's ceiling, and refused if what is chosen now is not what that word names." + } + } + }, + "outputSchema": { + "$id": "wai-quantum://schemas/run_routed/1", + "type": "object", + "description": "A job as a host returns it: its status, the method its plan chose and why, the request as submitted, and, once it is done, the result with its receipt: a job's result, or for a set (a request with programs or a sweep, its method set) the set's result. The command line's run --json, the local MCP server's run_quantum_circuit and a run on the person's own provider give a finished job; the job service also gives its id and times, and a job still queued or running, or failed with its error. A job's receipt verifies from this document alone: request and result.", + "anyOf": [ + { + "title": "wai.quantum.job/1", + "description": "A job as a host returns it: its status, the method its plan chose and why, the request as submitted, and, once it is done, the result with its receipt: a job's result, or for a set (a request with programs or a sweep, its method set) the set's result. The command line's run --json, the local MCP server's run_quantum_circuit and a run on the person's own provider give a finished job; the job service also gives its id and times, and a job still queued or running, or failed with its error. A job's receipt verifies from this document alone: request and result.", + "type": "object", + "required": [ + "status", + "request" + ], + "properties": { + "id": { + "type": "string", + "description": "The job service's id for the job." + }, + "status": { + "enum": [ + "queued", + "running", + "done", + "failed", + "cancelled", + "interrupted" + ], + "description": "interrupted: the job service stopped while the job ran, after it had run it again once from its request, so it has no result; error says so." + }, + "method": { + "type": "string", + "description": "The method the plan chose; set for a set." + }, + "why": { + "type": "string", + "description": "Why the plan chose the method." + }, + "estimate": { + "type": "object", + "description": "What the plan admitted the job with.", + "required": [ + "memory_bytes", + "work" + ], + "properties": { + "memory_bytes": { + "type": "integer", + "minimum": 0 + }, + "work": { + "type": "integer", + "minimum": 0, + "description": "In the method's own unit." + } + } + }, + "request": { + "title": "wai.quantum.job-request/1", + "description": "A job as a client submits it: a program and what is asked of it, or a set: many programs (programs), or one over a grid of its inputs (sweep), run as one job. The command line, both MCP servers, the job service, the desktop app and the Studio read it alike, and a receipt seals it as it was given. A member the engine does not read is ignored, and sealed with the rest.", + "type": "object", + "anyOf": [ + { + "required": [ + "qasm" + ] + }, + { + "required": [ + "programs" + ] + }, + { + "required": [ + "source" + ] + } + ], + "properties": { + "qasm": { + "type": "string", + "description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use." + }, + "source": { + "type": "object", + "required": [ + "format" + ], + "description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.", + "properties": { + "format": { + "enum": [ + "qasm", + "qir", + "jeff" + ] + }, + "program": { + "type": "string", + "description": "The program's text (OpenQASM, QIR)." + }, + "program_base64": { + "type": "string", + "description": "The program's bytes as base64 (jeff)." + } + } + }, + "shots": { + "type": "integer", + "minimum": 0, + "maximum": 1000000, + "description": "Measurement shots; 1024 when no observables or amplitudes are asked for, otherwise 0." + }, + "seed": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "description": "The sampling seed (1 when not given): the same job and seed give the same counts." + }, + "method": { + "type": "string", + "description": "auto (the default: the strongest method the program admits), or a method by its name as the methods list names it; pulse runs a pulse program (OpenPulse calibrations) under the pulse options." + }, + "observables": { + "type": "array", + "maxItems": 256, + "description": "Pauli observables to take the expectation values of.", + "items": { + "anyOf": [ + { + "type": "string", + "description": "A Pauli string, as \"Z0 Z1\"; qubits count from 0." + }, + { + "type": "object", + "required": [ + "pauli" + ], + "properties": { + "pauli": { + "type": "string", + "description": "A Pauli string, as \"X3\"." + }, + "coeff": { + "type": "number", + "description": "Its coefficient (1 when not given)." + } + } + } + ] + } + }, + "amplitudes": { + "type": "array", + "maxItems": 64, + "description": "Basis states whose amplitudes to return: one 0 or 1 per qubit, qubit n-1 first.", + "items": { + "type": "string" + } + }, + "noise": { + "type": "object", + "description": "A noise model, each channel a probability. A channel not listed here is refused.", + "additionalProperties": false, + "properties": { + "depolarizing_1q": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "depolarizing_2q": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "amplitude_damping": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "dephasing": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "readout": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + } + }, + "options": { + "type": "object", + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } + }, + "compile": { + "type": "object", + "description": "What a compile is asked for, each optional: the most the output may differ from the program (epsilon, in the operator norm up to a global phase), the level (0 lowers and approximates; 1 also rewrites and folds phases; 2 also resynthesises), the basis, the gate set it writes the program in (clifford_t: every rotation off the multiples of π/4 a Clifford+T word; standard: nothing approximated), whether to give the circuit after each pass (stages), and the twirl and dd passes, last (twirl, with its seed; dd, with its sequence).", + "properties": { + "epsilon": { + "type": "number", + "exclusiveMinimum": 0 + }, + "level": { + "type": "integer", + "minimum": 0, + "maximum": 2 + }, + "basis": { + "enum": [ + "clifford_t", + "standard" + ] + }, + "stages": { + "type": "boolean" + }, + "twirl": { + "description": "Twirl each two-qubit Clifford gate with Paulis drawn from a seeded stream: true (seed 1), or {\"seed\": N}. One seed is one instance, checked to be the same circuit.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "seed" + ], + "properties": { + "seed": { + "type": "integer", + "minimum": 0 + } + } + } + ] + }, + "dd": { + "description": "Dynamical decoupling in each window where a qubit idles long enough: xx or xy4 (or {\"sequence\": …}), checked to change nothing without noise.", + "anyOf": [ + { + "enum": [ + "xx", + "xy4" + ] + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "sequence": { + "enum": [ + "xx", + "xy4" + ] + } + } + } + ] + } + } + }, + "intent": { + "description": "What the program must do, checked with the run: one intent or a list. The result's verdict says how far it was checked.", + "anyOf": [ + { + "type": "object", + "description": "One of distribution, equivalent, prepares or sampled, with its options.", + "properties": { + "distribution": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "tolerance": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "equivalent": { + "type": "string" + }, + "prepares": { + "type": "string" + }, + "sampled": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "test": { + "enum": [ + "chi_squared", + "g_test" + ] + }, + "alpha": { + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "seed": { + "type": "integer", + "minimum": 0 + }, + "require": { + "const": "proof" + }, + "note": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "description": "One of distribution, equivalent, prepares or sampled, with its options.", + "properties": { + "distribution": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "tolerance": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "equivalent": { + "type": "string" + }, + "prepares": { + "type": "string" + }, + "sampled": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "test": { + "enum": [ + "chi_squared", + "g_test" + ] + }, + "alpha": { + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "seed": { + "type": "integer", + "minimum": 0 + }, + "require": { + "const": "proof" + }, + "note": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + } + ] + }, + "verdict": { + "type": "boolean", + "description": "true: the result carries a verdict even with no intent." + }, + "target": { + "description": "A device target: a built-in target's name, or a target document. The program is compiled to it, placed and simulated under its noise; noise may not be given beside it.", + "anyOf": [ + { + "type": "string" + }, + { + "title": "wai.quantum.target/1", + "description": "A device target: its qubits, the pairs it couples, its native gates with their errors and durations, and the calibration snapshot they come from. A value not known is left out, never written as zero. Every field but format, name, source, qubits, gates and coupling is optional, and a field the format does not name is refused, so a misspelt one never reads as absent. Its canonical text is its RFC 8785 form, and the BLAKE3 of that text, the target's hash, names the snapshot in a receipt.", + "type": "object", + "required": [ + "format", + "name", + "source", + "qubits", + "gates", + "coupling" + ], + "additionalProperties": false, + "properties": { + "format": { + "const": "wai.quantum.target/1" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 200 + }, + "source": { + "type": "object", + "required": [ + "format" + ], + "additionalProperties": false, + "properties": { + "format": { + "type": "string", + "description": "The format the target was read from (wai-quantum targets import --help lists them)." + }, + "note": { + "type": "string", + "maxLength": 400 + } + } + }, + "calibration": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "maxLength": 400, + "description": "The calibration snapshot's id, as the source names it, or a content id of the snapshot read." + }, + "timestamp": { + "type": "string", + "maxLength": 400, + "description": "When the snapshot was taken, as the source writes it." + } + } + }, + "qubits": { + "type": "array", + "minItems": 1, + "maxItems": 2048, + "description": "Every qubit, in order.", + "items": { + "type": "object", + "required": [ + "qubit" + ], + "additionalProperties": false, + "properties": { + "qubit": { + "type": "integer", + "minimum": 0, + "description": "Its index: its place in the list." + }, + "label": { + "type": "string", + "description": "The source's own name for it, when that is not its index." + }, + "t1_us": { + "type": "number", + "minimum": 0, + "description": "T1, microseconds." + }, + "t2_us": { + "type": "number", + "minimum": 0, + "description": "T2 (the echo or Ramsey time the source reports), microseconds." + }, + "frequency_ghz": { + "type": "number", + "minimum": 0, + "description": "Its frequency, gigahertz." + }, + "readout": { + "type": "object", + "required": [ + "p01", + "p10" + ], + "additionalProperties": false, + "properties": { + "p01": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "P(reads 1 | holds 0)." + }, + "p10": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "P(reads 0 | holds 1)." + } + } + }, + "measure_ns": { + "type": "number", + "minimum": 0, + "description": "The measurement's duration, nanoseconds." + } + } + } + }, + "gates": { + "type": "array", + "maxItems": 262144, + "description": "Each native gate where the device runs it, sorted by gate then qubits.", + "items": { + "type": "object", + "required": [ + "gate", + "qubits" + ], + "additionalProperties": false, + "properties": { + "gate": { + "type": "string", + "pattern": "^[a-z0-9_]{1,40}$" + }, + "qubits": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "items": { + "type": "integer", + "minimum": 0 + } + }, + "error": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "The average gate infidelity." + }, + "duration_ns": { + "type": "number", + "minimum": 0, + "description": "Nanoseconds." + } + } + } + }, + "coupling": { + "type": "array", + "description": "The pairs a two-qubit gate may act on, each once, the lower qubit first, sorted.", + "items": { + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "integer", + "minimum": 0 + } + } + } + } + } + ] + }, + "fabric": { + "description": "Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than this host's CPU for the job's size and fusion width, otherwise on the CPU), cpu, accelerator (the first accelerator member certified bit-exact here that holds the state, falling back to the next if it fails during the run), a member's id or key (wai-quantum fabric lists them), or a list of members, a power of two of them, the state split by its top qubits into one partition on each (cpu is a member, and a member may be named more than once). A member certified bit-exact gives the CPU's bits. A placement this host cannot honour is refused (J013), never made elsewhere.", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "array", + "minItems": 2, + "maxItems": 64, + "items": { + "type": "string", + "minLength": 1 + } + } + ] + }, + "repair": { + "description": "Repair the program first on its flagged lines: true, or the choices.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "max_iterations": { + "type": "integer", + "minimum": 1 + }, + "dyadic_bits": { + "type": "integer", + "minimum": 1, + "maximum": 32 + }, + "sizes": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + } + } + } + ] + }, + "history": { + "type": "object", + "description": "The program's history's account of the version the job runs: its digest, and the gates and lines in each hand. The receipt binds it; a history recomputes and checks it." + }, + "provider": { + "type": "string", + "description": "The person's own provider to run on, by the name their registry gives it. Only a host that holds their credentials runs such a job; every other host refuses it." + }, + "programs": { + "type": "array", + "minItems": 1, + "items": { + "anyOf": [ + { + "type": "string", + "description": "A program's text." + }, + { + "type": "object", + "required": [ + "qasm" + ], + "description": "A job of its own, read as a job request is (no programs or sweep in it); each item of the set's result holds its request in full." + } + ] + }, + "description": "A set (engine::sets): the programs to run as one job, each a program's text or a job of its own; the request's other fields apply to every item that does not set them itself." + }, + "sweep": { + "type": "object", + "additionalProperties": { + "type": "array", + "minItems": 1, + "items": { + "type": "number" + } + }, + "description": "A set over the request's own qasm: values for each of the program's inputs (integer, float or angle), every combination run, the names in sorted order and the first varying slowest." + }, + "params": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "A value for each of the program's parameters (`input float theta;`, `input angle phi;`), bound exactly before the program is read: it runs as if each were written as a `const` at that double. A parameter left without a value is refused (Q114, J050). In a sweep, the parameters it fixes, each bound at every point." + }, + "dry_run": { + "type": "boolean", + "description": "With true: what the host would do with the job or set, running nothing." + }, + "mitigate": { + "description": "Mitigate the job's expectation values (or, for readout, its counts) under its noise (engine::mitigate): zne, pea, pec, cdr, vd or readout, or {\"method\", …} with its options. The result's mitigation gives each value raw and mitigated.", + "anyOf": [ + { + "enum": [ + "zne", + "pea", + "pec", + "cdr", + "vd", + "readout" + ] + }, + { + "type": "object", + "required": [ + "method" + ] + } + ] + }, + "pulse": { + "type": "object", + "description": "A pulse run's options (method \"pulse\"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0.", + "additionalProperties": false, + "properties": { + "dt_ns": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1000, + "description": "The sample period, ns (default 0.5)." + }, + "levels": { + "type": "integer", + "enum": [ + 2, + 3 + ], + "description": "Levels kept per qubit (default 2; 3 shows leakage)." + }, + "tolerance": { + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1, + "description": "The most the stated error may be (default 1e-6): a run whose bound and rounding estimate pass it is refused, naming the steps that would meet it." + }, + "substeps": { + "type": "integer", + "minimum": 1, + "maximum": 4096, + "description": "Steps per sample (default: chosen so each step times the generator's norm is at most 0.5)." + }, + "qubits": { + "type": "object", + "description": "Each qubit's parameters by its index, over the target's and the defaults.", + "additionalProperties": { + "type": "object", + "additionalProperties": false, + "properties": { + "frequency_ghz": { + "type": "number", + "description": "Its frequency, GHz." + }, + "rabi_mhz": { + "type": "number", + "description": "Its Rabi frequency at full amplitude, MHz." + }, + "anharmonicity_mhz": { + "type": "number", + "description": "Its anharmonicity, MHz." + }, + "t1_us": { + "type": "number", + "description": "Its relaxation time, µs." + }, + "t2_us": { + "type": "number", + "description": "Its coherence time, µs (at most 2·T1)." + } + } + } + }, + "couplings": { + "type": "array", + "description": "Static ZZ couplings.", + "items": { + "type": "object", + "required": [ + "qubits", + "zz_khz" + ], + "additionalProperties": false, + "properties": { + "qubits": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 2, + "maxItems": 2 + }, + "zz_khz": { + "type": "number", + "description": "The coupling's rate, kHz." + } + } + } + }, + "ports": { + "type": "object", + "description": "Ports by name: what each is for and the qubit it reaches.", + "additionalProperties": { + "type": "object", + "required": [ + "kind", + "qubit" + ], + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "drive", + "measure", + "acquire" + ] + }, + "qubit": { + "type": "integer", + "minimum": 0 + } + } + } + } + } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } + } + } + }, + "result": { + "anyOf": [ + { + "title": "wai.quantum.job-result/1", + "description": "A job's result as the engine gives it, on every host: what was asked of the program, computed by the method its plan chose, with that method's accuracy class. The receipt seals the result without its receipt member, beside the request. A result names the engine that made it and this schema (engine and schema); results made before results carried them have neither and follow this schema all the same.", + "type": "object", + "required": [ + "method", + "qubits", + "gates", + "accuracy" + ], + "properties": { + "engine": { + "type": "object", + "description": "The engine that made the result: the wai-quantum crate's name and version.", + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "const": "wai-quantum" + }, + "version": { + "type": "string", + "description": "Its semantic version, as MAJOR.MINOR.PATCH." + } + } + }, + "schema": { + "const": "wai.quantum.job-result/1", + "description": "The schema the result follows." + }, + "components": { + "type": "array", + "description": "The identity of every component that made the result, when a registered one took part (engine::registry): its program's format, the passes its compile ran, the noise channels it names, its method; each registered one marked so. Sealed by the receipt with the rest.", + "items": { + "type": "object", + "description": "One component that made the result (engine::registry): its kind, name and version, the BLAKE3 digest of its descriptor, and whether it is built in. A result carries these only when a registered component took part; one made by built-ins alone names them as it always has (its method, its compile's passes, its noise's channels and the engine's version), the digests of that version listed by the components list.", + "required": [ + "kind", + "name", + "version", + "digest", + "origin" + ], + "properties": { + "kind": { + "enum": [ + "method", + "pass", + "channel", + "front_end" + ] + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "digest": { + "type": "string", + "pattern": "^[0-9a-f]{64}$", + "description": "BLAKE3 of the component's descriptor in its canonical JSON (engine::registry::digest_of)." + }, + "origin": { + "enum": [ + "built-in", + "registered" + ], + "description": "built-in: the engine's own; registered: a host's own, added in its process, not part of the engine." + }, + "certified": { + "const": false, + "description": "Beside a registered component: the engine does not certify it." + } + } + } + }, + "method": { + "type": "string", + "description": "The method that ran the job (provider for a run on the person's own provider)." + }, + "qubits": { + "type": "integer", + "minimum": 0 + }, + "gates": { + "type": "integer", + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "state_hash": { + "type": "string", + "description": "The bit-exact method's statevector hash (BLAKE3, hex): the same on every machine." + }, + "counts": { + "type": "object", + "description": "Outcomes and their counts, keyed by the program's classical bits, the highest bit first. At most 65536 outcomes are listed; omitted_shots holds the rest.", + "additionalProperties": { + "type": "integer", + "minimum": 0 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "outcome_dimension": { + "type": "integer", + "minimum": 0, + "description": "The stabilizer method: the dimension of the measured outcomes' affine space." + }, + "shots": { + "type": "integer", + "minimum": 0, + "description": "The shots, where the method names them in the result (trajectories, provider)." + }, + "expectations": { + "type": "array", + "items": { + "type": "object", + "required": [ + "observable", + "coeff", + "value" + ], + "properties": { + "observable": { + "type": "string" + }, + "coeff": { + "type": "number" + }, + "value": { + "type": "number", + "description": "The coefficient times the expectation value." + }, + "stderr": { + "type": "number", + "description": "The standard error, for an estimate." + }, + "bound": { + "type": "number", + "description": "A bound on |exact − value|: rigorous for the bounded class; with confidence beside it, holding with that probability." + }, + "peak_terms": { + "type": "integer" + }, + "threshold_reached": { + "type": "number" + }, + "max_terms": { + "type": "integer" + }, + "ladder": { + "type": "array", + "description": "The value at thresholds a decade apart, the asked one last.", + "items": { + "type": "object", + "required": [ + "threshold", + "value", + "bound" + ], + "properties": { + "threshold": { + "type": "number" + }, + "value": { + "type": "number" + }, + "bound": { + "type": "number" + }, + "peak_terms": { + "type": "integer" + }, + "threshold_reached": { + "type": "number" + } + } + } + }, + "confidence": { + "type": "number", + "description": "The probability the bound holds, for a bound that holds with a stated probability (stabilizer_rank's sampled mode)." + } + } + } + }, + "amplitudes": { + "type": "array", + "items": { + "type": "object", + "required": [ + "bits", + "re", + "im" + ], + "properties": { + "bits": { + "type": "string", + "description": "One 0 or 1 per qubit, qubit n-1 first." + }, + "re": { + "type": "number" + }, + "im": { + "type": "number" + }, + "bound": { + "type": "number", + "minimum": 0, + "description": "A bound on |exact − value| of the amplitude, holding with the probability confidence states (stabilizer_rank's sampled mode)." + }, + "confidence": { + "type": "number", + "description": "The probability the bound holds." + } + } + } + }, + "global_phase": { + "type": "string", + "description": "Why the amplitudes' global phase is not fixed, when it is not." + }, + "warning": { + "type": "string" + }, + "contraction_flops": { + "type": "number", + "description": "The tensor network's contraction cost." + }, + "dynamic": { + "type": "object", + "description": "A program that measures in the middle, resets or branches on a measured bit: how it ran.", + "properties": { + "measurements_and_resets": { + "type": "integer", + "minimum": 0 + }, + "branches_run": { + "type": "integer", + "minimum": 0 + }, + "states_at_once": { + "type": "integer", + "minimum": 0 + }, + "branches_weighed": { + "type": "integer", + "minimum": 0 + } + } + }, + "outputs": { + "type": "array", + "description": "The program's output declarations: each its name and type, and its value, or the places of its bits in each outcome.", + "items": { + "type": "object", + "required": [ + "name", + "type" + ], + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "bits": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "value": { + "description": "A number, a boolean, a bit string, a duration's text, {\"re\", \"im\"}, or an array of them." + } + } + } + }, + "timing": { + "type": "object", + "description": "A program that states durations (delay, box, stretch) the method does not apply: said so, with the reader's code.", + "required": [ + "applied", + "why" + ], + "properties": { + "applied": { + "type": "boolean" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "diagnostics": { + "type": "array", + "description": "The reader's warnings and notes on the program, each with its code.", + "items": { + "type": "object", + "description": "One of the reader's diagnostics: its code, what happens to the construct it is about, its message (without the line or the code), and where it stands.", + "required": [ + "code", + "outcome", + "message" + ], + "properties": { + "code": { + "type": "string" + }, + "outcome": { + "enum": [ + "refused", + "lowered", + "carried", + "preserved", + "warned" + ] + }, + "message": { + "type": "string" + }, + "line": { + "type": "integer", + "minimum": 1 + }, + "column": { + "type": "integer", + "minimum": 1 + }, + "length": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "compiled": { + "description": "How the program was compiled before it ran: on the person's own provider, to the device's gates; or, asked with compile, to a basis within a budget. Either way, basis is the gate set it was compiled to.", + "anyOf": [ + { + "type": "object", + "description": "A provider job: the program sent, compiled exactly to the device's own gates: its basis (the device's gate set), its OpenQASM 3 text (qasm3) and that text's BLAKE3 (program), its counts of gates and swaps, its layouts, and the check it passed before it was sent. Results sealed before qasm3 carry the hash alone.", + "required": [ + "basis", + "program" + ], + "properties": { + "basis": { + "type": "string" + }, + "program": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "qasm3": { + "type": "string", + "description": "The program sent, as OpenQASM 3, $i being index i of the coupling map the provider described; program is the BLAKE3 of its UTF-8 bytes." + }, + "qubit_names": { + "type": "object", + "additionalProperties": { + "type": "string", + "minLength": 1 + }, + "description": "The device's own name for each index the program uses, as it was when the job was sent, where a client sends it under those names." + }, + "native_gates": { + "type": "integer" + }, + "two_qubit_gates": { + "type": "integer" + }, + "swaps": { + "type": "integer" + }, + "layout": { + "type": "array", + "items": { + "type": "integer" + } + }, + "final_layout": { + "type": "array", + "items": { + "type": "integer" + } + }, + "checked": { + "type": "string" + }, + "placement": { + "type": "object", + "description": "Where the program was placed on the device's qubits, and why." + } + } + }, + { + "type": "object", + "description": "A job asked to compile its program first: what ran is the compiled circuit, within distance of the program in the operator norm up to a global phase.", + "required": [ + "basis", + "verdict" + ], + "properties": { + "basis": { + "enum": [ + "clifford_t", + "standard" + ], + "description": "The gate set the program was compiled to." + }, + "level": { + "type": "integer", + "minimum": 0 + }, + "epsilon": { + "type": "number", + "description": "The budget asked for." + }, + "distance": { + "type": [ + "number", + "null" + ], + "description": "The bound the passes' distances add to." + }, + "verdict": { + "type": "string" + }, + "source": { + "type": "object", + "description": "A circuit's counts, as the compiler counts them.", + "properties": { + "gates": { + "type": "integer", + "minimum": 0 + }, + "one_qubit": { + "type": "integer", + "minimum": 0 + }, + "two_qubit": { + "type": "integer", + "minimum": 0 + }, + "three_qubit": { + "type": "integer", + "minimum": 0 + }, + "cnots": { + "type": "integer", + "minimum": 0 + }, + "t_count": { + "type": "integer", + "minimum": 0 + }, + "rotations": { + "type": "integer", + "minimum": 0 + }, + "depth": { + "type": "integer", + "minimum": 0 + } + } + }, + "output": { + "type": "object", + "description": "A circuit's counts, as the compiler counts them.", + "properties": { + "gates": { + "type": "integer", + "minimum": 0 + }, + "one_qubit": { + "type": "integer", + "minimum": 0 + }, + "two_qubit": { + "type": "integer", + "minimum": 0 + }, + "three_qubit": { + "type": "integer", + "minimum": 0 + }, + "cnots": { + "type": "integer", + "minimum": 0 + }, + "t_count": { + "type": "integer", + "minimum": 0 + }, + "rotations": { + "type": "integer", + "minimum": 0 + }, + "depth": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": [ + "string", + "null" + ], + "description": "The BLAKE3 of the compile certificate's RFC 8785 text, in hex." + }, + "note": { + "type": "string" + } + } + } + ] + }, + "verdict": { + "title": "wai.quantum.verdict/1", + "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", + "type": "object", + "required": [ + "schema", + "level", + "rank", + "holds", + "statement", + "parsed", + "executed", + "intent", + "critique", + "repairs" + ], + "properties": { + "schema": { + "const": "wai.quantum.verdict/1" + }, + "level": { + "enum": [ + "refused", + "parsed", + "executed", + "evidence", + "proof" + ] + }, + "rank": { + "type": "integer", + "minimum": 0, + "maximum": 4, + "description": "The level's place on the ladder, from 0 (refused) to 4 (proof)." + }, + "holds": { + "type": [ + "boolean", + "null" + ] + }, + "statement": { + "type": "string", + "description": "The level in one plain line." + }, + "parsed": { + "type": "object", + "description": "Whether the reader took the program, and its warnings and notes with their codes, or its refusal.", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "diagnostics": { + "type": "array", + "items": { + "type": "object", + "description": "One of the reader's diagnostics: its code, what happens to the construct it is about, its message (without the line or the code), and where it stands.", + "required": [ + "code", + "outcome", + "message" + ], + "properties": { + "code": { + "type": "string" + }, + "outcome": { + "enum": [ + "refused", + "lowered", + "carried", + "preserved", + "warned" + ] + }, + "message": { + "type": "string" + }, + "line": { + "type": "integer", + "minimum": 1 + }, + "column": { + "type": "integer", + "minimum": 1 + }, + "length": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "code": { + "type": "string" + }, + "outcome": { + "enum": [ + "refused", + "retry", + "failed", + "lowered", + "carried", + "preserved", + "warned", + "dropped", + "defaulted" + ] + }, + "message": { + "type": "string" + }, + "line": { + "type": "integer", + "minimum": 1 + }, + "column": { + "type": "integer", + "minimum": 1 + }, + "length": { + "type": "integer", + "minimum": 0 + }, + "text": { + "type": "string", + "description": "The refusal as the reader wrote it, with its line and code." + } + } + }, + "executed": { + "type": [ + "object", + "null" + ], + "description": "The method that ran and its accuracy class, and the distance a compile put between the program and what ran.", + "properties": { + "method": { + "type": "string" + }, + "accuracy": { + "type": [ + "string", + "null" + ] + }, + "compiled_distance": { + "type": [ + "number", + "null" + ] + } + } + }, + "intent": { + "type": "array", + "items": { + "type": "object", + "description": "One intent's check: what it asked, whether it held, how strong the check was and how it was made.", + "required": [ + "kind", + "outcome", + "strength", + "how" + ], + "properties": { + "kind": { + "enum": [ + "distribution", + "equivalent", + "prepares", + "sampled", + "compiled" + ] + }, + "outcome": { + "enum": [ + "holds", + "fails", + "unchecked" + ] + }, + "strength": { + "enum": [ + "proof", + "evidence", + "none" + ] + }, + "how": { + "type": "string" + }, + "why": { + "type": "string" + }, + "distance": { + "type": "number" + }, + "tolerance": { + "type": "number" + }, + "outcomes": { + "type": "integer", + "description": "The outcomes the distribution holds, or the samples' distinct outcomes." + }, + "distribution": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "The program's distribution, when its outcomes are few enough to list." + }, + "largest_gaps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "outcome": { + "type": "string" + }, + "program": { + "type": "number" + }, + "intent": { + "type": "number" + } + } + } + }, + "global_phase": { + "type": [ + "number", + "null" + ] + }, + "method": { + "type": "string", + "description": "A sampled intent: the method the samples were run by." + }, + "seed": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "alpha": { + "type": "number" + }, + "fit": { + "type": "object", + "description": "A sampled intent: the test, its statistic, degrees of freedom and p-value, the level, and whether it rejected.", + "properties": { + "test": { + "type": "string" + }, + "statistic": { + "type": "number" + }, + "dof": { + "type": "integer" + }, + "p_value": { + "type": "number" + }, + "alpha": { + "type": "number" + }, + "shots": { + "type": "integer" + }, + "rejected": { + "type": "boolean" + }, + "smallest_expected": { + "type": [ + "number", + "null" + ] + }, + "impossible": { + "type": [ + "integer", + "array", + "boolean" + ] + }, + "note": { + "type": "string" + } + } + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "note": { + "type": "string" + } + } + } + }, + "critique": { + "type": "array", + "description": "The program's smells, each with its lines.", + "items": { + "type": "object" + } + }, + "repairs": { + "type": "array", + "description": "Each edit a repair made, with the code it answered and the lines it changed.", + "items": { + "type": "object" + } + }, + "refusal": { + "type": "object", + "description": "For a refused job: its message and its codes.", + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "codes": { + "type": "array", + "items": { + "type": "string" + } + }, + "outcome": { + "enum": [ + "refused", + "retry", + "failed", + "lowered", + "carried", + "preserved", + "warned", + "dropped", + "defaulted" + ] + }, + "meaning": { + "type": "string" + } + } + }, + "sealed": { + "type": "boolean" + } + } + }, + "target": { + "type": "object", + "description": "A run on a device target: which target (its hash, as its receipt binds it), its calibration snapshot, where the program was placed and why, and the noise derived from the target.", + "required": [ + "name", + "hash" + ], + "properties": { + "name": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "hash_is": { + "type": "string" + }, + "calibration": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + } + }, + "source": { + "type": "object", + "properties": { + "format": { + "type": "string" + }, + "note": { + "type": "string" + } + } + }, + "placement": { + "type": "object", + "description": "The native gate set, the layout and routes chosen, the swaps, the expected success beside the fewest-swaps layout's, and the check of the compiled program." + }, + "noise": { + "type": "object", + "description": "The noise model derived from the target's calibration: its channels, durations and idling, and each qubit's readout." + } + } + }, + "fabric": { + "type": "object", + "description": "Where the state vector, or the pauli method's sum of terms, ran: the kernel, the placement the job asked for, the member that ran it (or each partition's), each with its certificate, and the energy. Present when the job asked for a placement, or when auto placed the state on a member by measurement (`auto`); a job auto leaves on the CPU names nothing; the receipt seals it with the rest of the result. Every member placed is certified bit-exact, so the answers are the CPU's, byte for byte.", + "required": [ + "kernel", + "asked", + "parity", + "energy" + ], + "properties": { + "kernel": { + "type": "string" + }, + "asked": { + "description": "The placement the job asked for, as it gave it.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "member": { + "type": "string" + }, + "key": { + "type": "string" + }, + "class": { + "type": "string" + }, + "implementation": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "wide": { + "type": "object", + "description": "A member's certificate for gates on more than three qubits at once (wai.quantum.sv/run-wide): a fusion width of 4 to 6, or a wider gate, runs kernels the pinned corpus does not reach, certified on a corpus of their own (sv64-wide-v1). A member is placed for such a job only when this certificate is bit-exact; one that is not, or has none, says why and runs only gates on up to three qubits at once.", + "required": [ + "parity" + ], + "properties": { + "kernel": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "why": { + "type": "string" + } + } + }, + "partitions": { + "type": "array", + "description": "Each partition's member, by the value of the state's top qubits: partition i holds the amplitudes whose top bits read i.", + "items": { + "type": "object", + "description": "A member of the fabric and its certificate for the kernel: its id (which binds the device), its key, its class, the implementation, the parity tier, the certificate's digest (BLAKE3, hex), and the corpus it was earned on (its digest, generator and cases; the CPU reference's own standing has none).", + "required": [ + "member", + "implementation", + "parity", + "certificate" + ], + "properties": { + "member": { + "type": "string" + }, + "key": { + "type": "string" + }, + "class": { + "type": "string" + }, + "implementation": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "wide": { + "type": "object", + "description": "A member's certificate for gates on more than three qubits at once (wai.quantum.sv/run-wide): a fusion width of 4 to 6, or a wider gate, runs kernels the pinned corpus does not reach, certified on a corpus of their own (sv64-wide-v1). A member is placed for such a job only when this certificate is bit-exact; one that is not, or has none, says why and runs only gates on up to three qubits at once.", + "required": [ + "parity" + ], + "properties": { + "kernel": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "why": { + "type": "string" + } + } + }, + "why": { + "type": "string", + "description": "For a member the job fell back from: how it failed." + } + } + } + }, + "partition_qubits": { + "type": "integer", + "minimum": 0 + }, + "local_qubits": { + "type": "integer", + "minimum": 0 + }, + "segments": { + "type": "integer", + "minimum": 0, + "description": "Runs of gates the partitions took in turn, between exchanges." + }, + "exchanges": { + "type": "integer", + "minimum": 0, + "description": "Partition qubits exchanged with local ones through the host's copy of the state." + }, + "fell_back_from": { + "type": "array", + "description": "An accelerator request whose member failed during the run: each member that failed, in turn, with how; the member named above ran the job.", + "items": { + "type": "object", + "description": "A member of the fabric and its certificate for the kernel: its id (which binds the device), its key, its class, the implementation, the parity tier, the certificate's digest (BLAKE3, hex), and the corpus it was earned on (its digest, generator and cases; the CPU reference's own standing has none).", + "required": [ + "member", + "implementation", + "parity", + "certificate" + ], + "properties": { + "member": { + "type": "string" + }, + "key": { + "type": "string" + }, + "class": { + "type": "string" + }, + "implementation": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "wide": { + "type": "object", + "description": "A member's certificate for gates on more than three qubits at once (wai.quantum.sv/run-wide): a fusion width of 4 to 6, or a wider gate, runs kernels the pinned corpus does not reach, certified on a corpus of their own (sv64-wide-v1). A member is placed for such a job only when this certificate is bit-exact; one that is not, or has none, says why and runs only gates on up to three qubits at once.", + "required": [ + "parity" + ], + "properties": { + "kernel": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "why": { + "type": "string" + } + } + }, + "why": { + "type": "string", + "description": "For a member the job fell back from: how it failed." + } + } + } + }, + "auto": { + "type": "object", + "description": "Why auto placed the state where it ran: the rule (a member is placed only where the committed measurements show it faster than this host's CPU for the job's size and fusion width) and the measured row it rests on, with the host, the day and the load it was measured under. Present only when auto placed a state on a member.", + "required": [ + "rule", + "host", + "fusion", + "from_qubits", + "to_qubits" + ], + "properties": { + "rule": { + "type": "string" + }, + "host": { + "type": "string", + "description": "The host's processor as the measurements name it (cpu--)." + }, + "measured": { + "type": "string", + "description": "The day the host was measured (UTC)." + }, + "about": { + "type": "string" + }, + "load": { + "type": "string" + }, + "discovery_ms": { + "type": "number", + "description": "What discovering and certifying the host's members took, once per process, as measured." + }, + "fusion": { + "type": "integer", + "minimum": 1 + }, + "from_qubits": { + "type": "integer", + "minimum": 0 + }, + "to_qubits": { + "type": "integer", + "minimum": 0 + }, + "min_launches": { + "type": "integer", + "minimum": 0 + }, + "basis": { + "type": "object", + "description": "The measured row the job is judged by: the largest measured size at or below its own, the launches of its plan, the runs of each, and the spread of the CPU's and the member's times in milliseconds.", + "required": [ + "qubits", + "launches", + "runs", + "cpu_ms", + "member_ms" + ], + "properties": { + "qubits": { + "type": "integer", + "minimum": 0 + }, + "launches": { + "type": "integer", + "minimum": 0 + }, + "runs": { + "type": "integer", + "minimum": 0 + }, + "cpu_ms": { + "type": "object", + "description": "The least, the median and the most of a measured row's runs, in milliseconds.", + "required": [ + "min", + "median", + "max" + ], + "properties": { + "min": { + "type": "number" + }, + "median": { + "type": "number" + }, + "max": { + "type": "number" + } + } + }, + "member_ms": { + "type": "object", + "description": "The least, the median and the most of a measured row's runs, in milliseconds.", + "required": [ + "min", + "median", + "max" + ], + "properties": { + "min": { + "type": "number" + }, + "median": { + "type": "number" + }, + "max": { + "type": "number" + } + } + } + } + } + } + }, + "energy": { + "description": "The CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or unmetered with the reason.", + "anyOf": [ + { + "type": "object", + "required": [ + "unmetered" + ], + "properties": { + "unmetered": { + "type": "string" + }, + "service_kwh": { + "type": "number", + "description": "A provider job: the provider's own figure." + }, + "service_kwh_is": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "joules_micro", + "energy_provenance", + "coverage" + ], + "properties": { + "joules_micro": { + "type": "integer", + "minimum": 1 + }, + "energy_provenance": { + "type": "string" + }, + "energy_uncertainty": { + "type": "object", + "properties": { + "relative_ppm": { + "type": "integer" + }, + "window_us": { + "type": "integer" + } + } + }, + "energy_counter_filtering": { + "type": "string" + }, + "coverage": { + "enum": [ + "whole", + "partial" + ] + }, + "covers": { + "type": "string" + }, + "excludes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpu_ms": { + "type": "integer" + }, + "source": { + "type": "string" + }, + "attribution": { + "enum": [ + "process", + "none" + ], + "description": "Whose energy it is: the job's worker process, or none (the processor packages' over the job's window, every process on the host in it)." + }, + "packages": { + "type": "integer", + "minimum": 1, + "description": "The processor packages read." + }, + "concurrent_jobs": { + "type": "integer", + "minimum": 0, + "description": "Other jobs that ran on the host during the window." + }, + "counter": { + "type": "object", + "description": "The package counter as seen: the longest it went between updates, and the smallest step it took.", + "properties": { + "update_us": { + "type": "integer", + "minimum": 0 + }, + "step_uj": { + "type": "integer", + "minimum": 0 + } + } + }, + "declared": { + "type": "string", + "description": "What the stated uncertainty covers, and what it does not." + } + } + } + ] + }, + "why": { + "type": "string" + } + } + }, + "repaired": { + "type": "object", + "description": "A job asked to repair its program first: the program that ran, each repair, and what needs a person.", + "properties": { + "qasm": { + "type": "string" + }, + "repairs": { + "type": "array", + "items": { + "type": "object", + "required": [ + "code", + "by", + "edits" + ], + "properties": { + "code": { + "type": "string" + }, + "rule": { + "type": "string" + }, + "by": { + "enum": [ + "engine", + "proposal" + ] + }, + "flagged": { + "type": "array", + "items": { + "type": "integer" + } + }, + "edits": { + "type": "array", + "items": { + "type": "object", + "properties": { + "line": { + "type": "integer" + }, + "before": { + "type": [ + "string", + "null" + ] + }, + "after": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + }, + "needs_person": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0, + "description": "Wall time of the run, where the host has a clock (not in a browser tab)." + }, + "energy": { + "description": "The CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or unmetered with the reason.", + "anyOf": [ + { + "type": "object", + "required": [ + "unmetered" + ], + "properties": { + "unmetered": { + "type": "string" + }, + "service_kwh": { + "type": "number", + "description": "A provider job: the provider's own figure." + }, + "service_kwh_is": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "joules_micro", + "energy_provenance", + "coverage" + ], + "properties": { + "joules_micro": { + "type": "integer", + "minimum": 1 + }, + "energy_provenance": { + "type": "string" + }, + "energy_uncertainty": { + "type": "object", + "properties": { + "relative_ppm": { + "type": "integer" + }, + "window_us": { + "type": "integer" + } + } + }, + "energy_counter_filtering": { + "type": "string" + }, + "coverage": { + "enum": [ + "whole", + "partial" + ] + }, + "covers": { + "type": "string" + }, + "excludes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpu_ms": { + "type": "integer" + }, + "source": { + "type": "string" + }, + "attribution": { + "enum": [ + "process", + "none" + ], + "description": "Whose energy it is: the job's worker process, or none (the processor packages' over the job's window, every process on the host in it)." + }, + "packages": { + "type": "integer", + "minimum": 1, + "description": "The processor packages read." + }, + "concurrent_jobs": { + "type": "integer", + "minimum": 0, + "description": "Other jobs that ran on the host during the window." + }, + "counter": { + "type": "object", + "description": "The package counter as seen: the longest it went between updates, and the smallest step it took.", + "properties": { + "update_us": { + "type": "integer", + "minimum": 0 + }, + "step_uj": { + "type": "integer", + "minimum": 0 + } + } + }, + "declared": { + "type": "string", + "description": "What the stated uncertainty covers, and what it does not." + } + } + } + ] + }, + "receipt": { + "anyOf": [ + { + "title": "wai.quantum.receipt/2", + "description": "A result's receipt: an Ed25519 signature, by the key it names, over digest = BLAKE3(\"wai:quantum-service-receipt\\x02\" ‖ len ‖ request ‖ len ‖ result), each of request and result in its RFC 8785 canonical text (the result without its receipt member), each length 8 bytes big-endian. Whatever members the request and the result hold are sealed, the result's engine and schema among them. The first receipts (no canon member, $defs/first) sealed their writer's compact text under the domain ending \\x01; they still verify. wai/extensions/quantum-providers.md section 8.2 states the seal in full, and section 8.4 what a verifier checks.", + "type": "object", + "required": [ + "alg", + "canon", + "key", + "digest", + "signature" + ], + "properties": { + "alg": { + "const": "ed25519" + }, + "canon": { + "const": "rfc8785", + "description": "The canonical form the digest is taken over." + }, + "key": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$", + "description": "The signing key, 32 bytes in lower-case hex." + }, + "digest": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$", + "description": "The digest signed, 32 bytes in lower-case hex." + }, + "signature": { + "type": "string", + "minLength": 128, + "maxLength": 128, + "pattern": "^[0-9a-f]{128}$", + "description": "The signature, 64 bytes in lower-case hex." + } + } + }, + { + "description": "The first form, before canon: the digest is over the compact text its writer wrote of each, members in the document's order (section 8.2 of wai/extensions/quantum-providers.md), under the domain ending \\x01. Never written now; still verified.", + "type": "object", + "required": [ + "alg", + "key", + "digest", + "signature" + ], + "properties": { + "alg": { + "const": "ed25519" + }, + "key": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$" + }, + "digest": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$" + }, + "signature": { + "type": "string", + "minLength": 128, + "maxLength": 128, + "pattern": "^[0-9a-f]{128}$" + } + } + } + ] + }, + "provider": { + "type": "object", + "description": "A provider job: the provider's name, kind and protocol, the device, its provenance, and the hash of its description." + }, + "counts_source": { + "enum": [ + "shots", + "vendor_counts", + "probabilities" + ], + "description": "A provider job: where its counts come from (wai/extensions/quantum-providers.md section 8.3): tallied from one record a shot (shots), the provider's own counts (vendor_counts), or rebuilt from the probabilities it returned by largest remainders, derived and not shot records (probabilities). Results sealed before it carry neither it nor execution." + }, + "execution": { + "type": "object", + "description": "A provider job: how the device was asked to run the program (section 8.3): who states it (stated_by: client, provider or nobody); what the client sent (sent: the request's members and the settings among them); each of mitigation, twirling, decoupling, remapping and optimisation (off, on, default when the request sets nothing for it, none when the device has no such step, unknown when nobody states it); whether the gates were to run as written (verbatim); and a note.", + "required": [ + "stated_by", + "mitigation", + "twirling", + "decoupling", + "remapping", + "optimisation", + "verbatim" + ], + "properties": { + "stated_by": { + "enum": [ + "client", + "provider", + "nobody" + ] + }, + "sent": { + "type": "object", + "required": [ + "fields", + "settings" + ], + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "settings": { + "type": "object" + } + }, + "additionalProperties": false + }, + "mitigation": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "twirling": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "decoupling": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "remapping": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "optimisation": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "verbatim": { + "type": [ + "boolean", + "null" + ] + }, + "note": { + "type": "string" + } + }, + "additionalProperties": false + }, + "calibration": { + "type": [ + "string", + "null" + ], + "description": "A provider job: the calibration snapshot it ran under." + }, + "job": { + "type": "object", + "description": "A provider job: the provider's job id and its status checks." + }, + "ideal": { + "description": "A provider job: the circuit's exact distribution set beside the measured counts.", + "anyOf": [ + { + "type": "object", + "required": [ + "computed", + "total_variation_distance", + "hellinger_fidelity" + ], + "properties": { + "computed": { + "const": true + }, + "method": { + "type": "string" + }, + "total_variation_distance": { + "type": "number" + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_expected": { + "type": "number" + }, + "ideal_outcomes": { + "type": "integer" + }, + "note": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "computed", + "why" + ], + "properties": { + "computed": { + "const": false + }, + "why": { + "type": "string" + } + } + } + ] + }, + "cost": { + "type": "object", + "description": "A provider job: the estimate shown before it was sent, what the provider says it charged, and whether the person confirmed a run that was not free." + }, + "provenance": { + "title": "wai.quantum.provenance/1", + "description": "What a result came from, under the five categories cross-platform provenance surveys use: the circuit, the computer, the compilation, the execution and the software. A host adds it to the results it seals (the job service does, and each item of a set); a result without it reads as it always did. wai-quantum-service/docs/provenance.md maps every field to where it is and whether the receipt seals it.", + "type": "object", + "required": [ + "schema", + "circuit", + "computer", + "compilation", + "execution", + "software" + ], + "properties": { + "schema": { + "const": "wai.quantum.provenance/1" + }, + "circuit": { + "type": "object", + "description": "The program: the BLAKE3 digest of its text as given, its qubits and its gates.", + "required": [ + "program" + ], + "properties": { + "program": { + "type": "string", + "description": "BLAKE3 of the program's text, in hex." + }, + "qubits": { + "type": "integer", + "minimum": 0 + }, + "gates": { + "type": [ + "integer", + "null" + ] + } + } + }, + "computer": { + "type": "object", + "description": "What ran it: a classical simulator, the method and its accuracy class, a device target's hash when the job named one, and the fabric's members when the result names where its state ran.", + "required": [ + "kind", + "method" + ], + "properties": { + "kind": { + "const": "simulator" + }, + "method": { + "type": "string" + }, + "accuracy": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": "string", + "description": "The device target's hash; its layout, routes and noise are in the result's own target." + }, + "fabric": { + "type": "object", + "description": "The kernel and the member that ran the state, or each partition's, as the result's fabric names them.", + "properties": { + "kernel": { + "type": "string" + }, + "members": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "compilation": { + "type": "object", + "description": "Whether the job asked to be compiled; if it did, each pass in order with its check's verdict, the certificate's digest, the gate set compiled to (its basis), the level, the ε budget and the distance the result carries, and that no pass draws a random number.", + "required": [ + "asked" + ], + "properties": { + "asked": { + "type": "boolean" + }, + "passes": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "pass": { + "type": "string" + }, + "verdict": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "certificate": { + "type": [ + "string", + "null" + ] + }, + "basis": { + "type": [ + "string", + "null" + ], + "description": "The gate set compiled to: clifford_t or standard." + }, + "level": { + "type": [ + "integer", + "null" + ] + }, + "epsilon": { + "type": [ + "number", + "null" + ] + }, + "distance": { + "type": [ + "number", + "null" + ] + }, + "seeded": { + "const": false + }, + "device": { + "type": "string", + "description": "A job on a device target, compiled exactly to its gates: where its layout and routes are." + }, + "status": { + "const": "not-applicable" + }, + "why": { + "type": "string" + } + } + }, + "execution": { + "type": "object", + "description": "The shots, the seed and the plan the job ran under; its identifier and times are the host's, outside the result.", + "required": [ + "plan" + ], + "properties": { + "shots": { + "type": [ + "integer", + "null" + ] + }, + "seed": { + "type": [ + "integer", + "null" + ] + }, + "plan": { + "type": "object", + "properties": { + "method": { + "type": "string" + }, + "why": { + "type": "string" + }, + "memory_bytes": { + "type": "integer", + "minimum": 0 + }, + "work": { + "type": "integer", + "minimum": 0 + } + } + } + } + }, + "software": { + "type": "object", + "description": "The engine's name and version, and the host's.", + "required": [ + "engine", + "host" + ], + "properties": { + "engine": { + "type": "string" + }, + "host": { + "type": "string" + } + } + } + } + }, + "mitigation": { + "title": "wai.quantum.mitigation/1", + "description": "A job's mitigation (its request's mitigate, engine::mitigate), in its result: the method and the options it ran with, its bias and variance assumptions, each observable raw and mitigated with a standard error each and the ideal value (or, for readout, the counts inverted as a quasi-distribution), the method's own details and what it spent. docs/qec.md describes each method.", + "type": "object", + "required": [ + "method", + "options", + "assumptions" + ], + "properties": { + "method": { + "enum": [ + "zne", + "pea", + "pec", + "cdr", + "vd", + "readout" + ] + }, + "options": { + "type": "object", + "description": "The options it ran with, the defaults filled in.", + "properties": { + "method": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "factors": { + "type": "array", + "items": { + "type": "number" + } + }, + "extrapolation": { + "enum": [ + "richardson", + "linear", + "exponential" + ] + }, + "samples": { + "type": "integer" + }, + "training": { + "type": "integer" + }, + "keep": { + "type": "integer" + }, + "learn_shots": { + "type": "integer" + } + } + }, + "assumptions": { + "type": "object", + "properties": { + "bias": { + "type": "string" + }, + "variance": { + "type": "string" + } + } + }, + "noise": { + "type": "string", + "description": "How the job's noise model is read for the method." + }, + "note": { + "type": "string" + }, + "observables": { + "type": "array", + "items": { + "type": "object", + "description": "One observable: its raw value and the mitigated one, each with its standard error, and the ideal value a simulation knows.", + "properties": { + "observable": { + "type": "string" + }, + "coeff": { + "type": "number" + }, + "raw": { + "type": "number" + }, + "raw_stderr": { + "type": "number" + }, + "mitigated": { + "type": "number" + }, + "stderr": { + "type": "number" + }, + "ideal": { + "type": "number" + } + } + } + }, + "distribution": { + "type": "array", + "description": "readout: each outcome's raw share and its mitigated quasi-probability, with its standard error.", + "items": { + "type": "object", + "properties": { + "bits": { + "type": "string" + }, + "raw": { + "type": "number" + }, + "mitigated": { + "type": "number" + }, + "stderr": { + "type": "number" + } + } + } + }, + "details": { + "type": "object", + "description": "The method's own: the folded scales and the folding check (zne), the learned model and the amplified values (pea), the quasi-probability and the value it converges to (pec), the training fits (cdr), the purity (vd), the flip and its amplification (readout).", + "additionalProperties": true + }, + "cost": { + "type": "object", + "description": "The circuits and shots it spent beyond the job's own.", + "properties": { + "circuits": { + "type": "integer", + "minimum": 0 + }, + "shots": { + "type": "integer", + "minimum": 0 + }, + "note": { + "type": "string" + } + } + } + } + }, + "pulse": { + "type": "object", + "description": "A pulse run (method pulse, engine::pulse): what was read and its distribution, the final populations, each capture's reading, the final density matrix's digest, the schedule's length, the integrator and its step, the device and where each parameter came from, and what the receipt binds (calibration).", + "required": [ + "read", + "outcome_bits", + "populations", + "simulated_qubits", + "density_hash", + "integrator", + "device", + "calibration" + ], + "properties": { + "read": { + "type": "string", + "description": "What the distribution reads: the captures together (into the program's bits when each writes one), or the final state." + }, + "outcome_bits": { + "type": "array", + "items": { + "type": "string" + }, + "description": "What each character of an outcome is, left to right: a program bit (c[0]) or a qubit ($0)." + }, + "distribution": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "number" + }, + "description": "The probability of each outcome, which the counts sample; null when the captures start at different samples." + }, + "populations": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "The final state read on every simulated qubit, the highest qubit first, a level above 0 read as 1." + }, + "simulated_qubits": { + "type": "array", + "items": { + "type": "integer" + } + }, + "captures": { + "type": "array", + "items": { + "type": "object", + "properties": { + "frame": { + "type": "string" + }, + "qubit": { + "type": "integer" + }, + "start": { + "type": "integer" + }, + "start_ns": { + "type": "number" + }, + "bit": { + "type": [ + "string", + "null" + ] + }, + "p1": { + "type": "number" + }, + "p2": { + "type": "number" + } + } + } + }, + "leakage": { + "type": "array", + "items": { + "type": "object", + "properties": { + "qubit": { + "type": "integer" + }, + "p2": { + "type": "number" + } + } + }, + "description": "With three levels: each qubit's final probability of level 2." + }, + "trace": { + "type": "number" + }, + "density_hash": { + "type": "string", + "description": "The BLAKE3 of the final density matrix's bits: the same on every platform." + }, + "duration": { + "type": "integer" + }, + "duration_ns": { + "type": "number" + }, + "integrator": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "dt_ns": { + "type": "number" + }, + "substeps": { + "type": "integer" + }, + "step_ns": { + "type": "number" + }, + "steps": { + "type": "integer" + }, + "norm_max": { + "type": "number" + }, + "frame": { + "type": "string" + } + } + }, + "device": { + "type": "object", + "properties": { + "levels": { + "type": "integer" + }, + "dt_ns": { + "type": "number" + }, + "qubits": { + "type": "array", + "items": { + "type": "object", + "properties": { + "qubit": { + "type": "integer" + }, + "frequency_hz": { + "type": "number" + }, + "rabi_hz": { + "type": "number" + }, + "anharmonicity_hz": { + "type": "number" + }, + "t1_ns": { + "type": "number" + }, + "t2_ns": { + "type": "number" + }, + "from": { + "type": "object", + "additionalProperties": { + "enum": [ + "pulse", + "target", + "default", + "none" + ] + } + } + } + } + }, + "couplings": { + "type": "array" + }, + "model": { + "type": "string" + } + } + }, + "calibration": { + "type": "object", + "description": "What the receipt binds: the program's, its calibrations', the schedule's and the device's digests, and the target snapshot.", + "properties": { + "program": { + "type": "string" + }, + "calibrations": { + "type": "string" + }, + "schedule": { + "type": "string" + }, + "device": { + "type": "string" + }, + "target": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "calibration": { + "type": "object" + } + } + } + } + }, + "not_modelled": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + }, + { + "title": "wai.quantum.set/1", + "description": "A set's result: many programs, or one program over a grid of its inputs, run as one job (engine::sets). Its head holds the count, how many items finished and failed, the Merkle root over the items' leaves, the set's energy and time; the set's receipt seals the set's request and its head. Each item is a plain job with its own receipt, its index, its point in a sweep, and its path to the root, so it is shown sealed by the set alone. A result names the engine that made it and this schema (engine and schema).", + "type": "object", + "required": [ + "format", + "count", + "done", + "failed", + "root", + "items" + ], + "properties": { + "engine": { + "type": "object", + "description": "The engine that made the result: the wai-quantum crate's name and version.", + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "const": "wai-quantum" + }, + "version": { + "type": "string" + } + } + }, + "schema": { + "const": "wai.quantum.set/1" + }, + "format": { + "const": "wai.quantum.set/1" + }, + "count": { + "type": "integer", + "minimum": 1 + }, + "done": { + "type": "integer", + "minimum": 0 + }, + "failed": { + "type": "integer", + "minimum": 0 + }, + "root": { + "type": "string", + "description": "The Merkle root of the items' leaves, in hex (domains moq-jwp:merkle-leaf and moq-jwp:merkle-node, version 1)." + }, + "energy": { + "description": "The CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or unmetered with the reason.", + "anyOf": [ + { + "type": "object", + "required": [ + "unmetered" + ], + "properties": { + "unmetered": { + "type": "string" + }, + "service_kwh": { + "type": "number", + "description": "A provider job: the provider's own figure." + }, + "service_kwh_is": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "joules_micro", + "energy_provenance", + "coverage" + ], + "properties": { + "joules_micro": { + "type": "integer", + "minimum": 1 + }, + "energy_provenance": { + "type": "string" + }, + "energy_uncertainty": { + "type": "object", + "properties": { + "relative_ppm": { + "type": "integer" + }, + "window_us": { + "type": "integer" + } + } + }, + "energy_counter_filtering": { + "type": "string" + }, + "coverage": { + "enum": [ + "whole", + "partial" + ] + }, + "covers": { + "type": "string" + }, + "excludes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpu_ms": { + "type": "integer" + }, + "source": { + "type": "string" + }, + "attribution": { + "enum": [ + "process", + "none" + ], + "description": "Whose energy it is: the job's worker process, or none (the processor packages' over the job's window, every process on the host in it)." + }, + "packages": { + "type": "integer", + "minimum": 1, + "description": "The processor packages read." + }, + "concurrent_jobs": { + "type": "integer", + "minimum": 0, + "description": "Other jobs that ran on the host during the window." + }, + "counter": { + "type": "object", + "description": "The package counter as seen: the longest it went between updates, and the smallest step it took.", + "properties": { + "update_us": { + "type": "integer", + "minimum": 0 + }, + "step_uj": { + "type": "integer", + "minimum": 0 + } + } + }, + "declared": { + "type": "string", + "description": "What the stated uncertainty covers, and what it does not." + } + } + } + ] + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "receipt": { + "title": "wai.quantum.receipt/2", + "description": "A result's receipt: an Ed25519 signature, by the key it names, over digest = BLAKE3(\"wai:quantum-service-receipt\\x02\" ‖ len ‖ request ‖ len ‖ result), each of request and result in its RFC 8785 canonical text (the result without its receipt member), each length 8 bytes big-endian. Whatever members the request and the result hold are sealed, the result's engine and schema among them. The first receipts (no canon member, $defs/first) sealed their writer's compact text under the domain ending \\x01; they still verify. wai/extensions/quantum-providers.md section 8.2 states the seal in full, and section 8.4 what a verifier checks.", + "type": "object", + "required": [ + "alg", + "canon", + "key", + "digest", + "signature" + ], + "properties": { + "alg": { + "const": "ed25519" + }, + "canon": { + "const": "rfc8785", + "description": "The canonical form the digest is taken over." + }, + "key": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$", + "description": "The signing key, 32 bytes in lower-case hex." + }, + "digest": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$", + "description": "The digest signed, 32 bytes in lower-case hex." + }, + "signature": { + "type": "string", + "minLength": 128, + "maxLength": 128, + "pattern": "^[0-9a-f]{128}$", + "description": "The signature, 64 bytes in lower-case hex." + } + } + }, + "items": { + "type": "array", + "items": { + "type": "object", + "description": "One item: its index, its point in a sweep, its request (a plain job, complete in itself), and its result with its own receipt, or why it failed; and its path to the set's root.", + "required": [ + "index", + "request", + "status", + "path" + ], + "properties": { + "index": { + "type": "integer", + "minimum": 0 + }, + "point": { + "type": "object", + "description": "A sweep's item: the value of each input it was run at." + }, + "status": { + "enum": [ + "done", + "failed" + ] + }, + "method": { + "type": "string" + }, + "why": { + "type": "string" + }, + "request": { + "title": "wai.quantum.job-request/1", + "description": "A job as a client submits it: a program and what is asked of it, or a set: many programs (programs), or one over a grid of its inputs (sweep), run as one job. The command line, both MCP servers, the job service, the desktop app and the Studio read it alike, and a receipt seals it as it was given. A member the engine does not read is ignored, and sealed with the rest.", + "type": "object", + "anyOf": [ + { + "required": [ + "qasm" + ] + }, + { + "required": [ + "programs" + ] + }, + { + "required": [ + "source" + ] + } + ], + "properties": { + "qasm": { + "type": "string", + "description": "The program, in OpenQASM 3 or the OpenQASM 2 forms in common use." + }, + "source": { + "type": "object", + "required": [ + "format" + ], + "description": "The program in another format, in place of qasm (engine::formats::expand): read to the job's qasm before the job is read, the request keeping its source.", + "properties": { + "format": { + "enum": [ + "qasm", + "qir", + "jeff" + ] + }, + "program": { + "type": "string", + "description": "The program's text (OpenQASM, QIR)." + }, + "program_base64": { + "type": "string", + "description": "The program's bytes as base64 (jeff)." + } + } + }, + "shots": { + "type": "integer", + "minimum": 0, + "maximum": 1000000, + "description": "Measurement shots; 1024 when no observables or amplitudes are asked for, otherwise 0." + }, + "seed": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991, + "description": "The sampling seed (1 when not given): the same job and seed give the same counts." + }, + "method": { + "type": "string", + "description": "auto (the default: the strongest method the program admits), or a method by its name as the methods list names it; pulse runs a pulse program (OpenPulse calibrations) under the pulse options." + }, + "observables": { + "type": "array", + "maxItems": 256, + "description": "Pauli observables to take the expectation values of.", + "items": { + "anyOf": [ + { + "type": "string", + "description": "A Pauli string, as \"Z0 Z1\"; qubits count from 0." + }, + { + "type": "object", + "required": [ + "pauli" + ], + "properties": { + "pauli": { + "type": "string", + "description": "A Pauli string, as \"X3\"." + }, + "coeff": { + "type": "number", + "description": "Its coefficient (1 when not given)." + } + } + } + ] + } + }, + "amplitudes": { + "type": "array", + "maxItems": 64, + "description": "Basis states whose amplitudes to return: one 0 or 1 per qubit, qubit n-1 first.", + "items": { + "type": "string" + } + }, + "noise": { + "type": "object", + "description": "A noise model, each channel a probability. A channel not listed here is refused.", + "additionalProperties": false, + "properties": { + "depolarizing_1q": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "depolarizing_2q": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "amplitude_damping": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "dephasing": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "readout": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + } + }, + "options": { + "type": "object", + "description": "Options of the method that runs the job, as the methods list names them (max_bond, cutoff, fusion, trajectories, threshold, max_weight, ladder, max_terms, path_restarts, controls), and memory_gb.", + "additionalProperties": true, + "properties": { + "controls": { + "enum": [ + "whole", + "standard" + ], + "description": "A gate whose standard gates would double (x, y, z or h under three or more controls; s, sdg, t, tdg, p, rx, ry, rz, u, sx or sxdg under two or more) runs as one on statevector and in standard gates on exact. \"standard\" runs standard gates on statevector too, which reproduces a result made that way bit for bit. \"whole\" holds the gate whole on exact too, which gives other bits than its default, and is refused (J003) on a job that runs standard gates: another method named, a compile, noise, mitigation, a device target or a named place on the fabric. Any other value is refused." + } + } + }, + "compile": { + "type": "object", + "description": "What a compile is asked for, each optional: the most the output may differ from the program (epsilon, in the operator norm up to a global phase), the level (0 lowers and approximates; 1 also rewrites and folds phases; 2 also resynthesises), the basis, the gate set it writes the program in (clifford_t: every rotation off the multiples of π/4 a Clifford+T word; standard: nothing approximated), whether to give the circuit after each pass (stages), and the twirl and dd passes, last (twirl, with its seed; dd, with its sequence).", + "properties": { + "epsilon": { + "type": "number", + "exclusiveMinimum": 0 + }, + "level": { + "type": "integer", + "minimum": 0, + "maximum": 2 + }, + "basis": { + "enum": [ + "clifford_t", + "standard" + ] + }, + "stages": { + "type": "boolean" + }, + "twirl": { + "description": "Twirl each two-qubit Clifford gate with Paulis drawn from a seeded stream: true (seed 1), or {\"seed\": N}. One seed is one instance, checked to be the same circuit.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "required": [ + "seed" + ], + "properties": { + "seed": { + "type": "integer", + "minimum": 0 + } + } + } + ] + }, + "dd": { + "description": "Dynamical decoupling in each window where a qubit idles long enough: xx or xy4 (or {\"sequence\": …}), checked to change nothing without noise.", + "anyOf": [ + { + "enum": [ + "xx", + "xy4" + ] + }, + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "sequence": { + "enum": [ + "xx", + "xy4" + ] + } + } + } + ] + } + } + }, + "intent": { + "description": "What the program must do, checked with the run: one intent or a list. The result's verdict says how far it was checked.", + "anyOf": [ + { + "type": "object", + "description": "One of distribution, equivalent, prepares or sampled, with its options.", + "properties": { + "distribution": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "tolerance": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "equivalent": { + "type": "string" + }, + "prepares": { + "type": "string" + }, + "sampled": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "test": { + "enum": [ + "chi_squared", + "g_test" + ] + }, + "alpha": { + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "seed": { + "type": "integer", + "minimum": 0 + }, + "require": { + "const": "proof" + }, + "note": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "description": "One of distribution, equivalent, prepares or sampled, with its options.", + "properties": { + "distribution": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "tolerance": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "equivalent": { + "type": "string" + }, + "prepares": { + "type": "string" + }, + "sampled": { + "type": "object", + "additionalProperties": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "test": { + "enum": [ + "chi_squared", + "g_test" + ] + }, + "alpha": { + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1 + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "seed": { + "type": "integer", + "minimum": 0 + }, + "require": { + "const": "proof" + }, + "note": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + } + ] + }, + "verdict": { + "type": "boolean", + "description": "true: the result carries a verdict even with no intent." + }, + "target": { + "description": "A device target: a built-in target's name, or a target document. The program is compiled to it, placed and simulated under its noise; noise may not be given beside it.", + "anyOf": [ + { + "type": "string" + }, + { + "title": "wai.quantum.target/1", + "description": "A device target: its qubits, the pairs it couples, its native gates with their errors and durations, and the calibration snapshot they come from. A value not known is left out, never written as zero. Every field but format, name, source, qubits, gates and coupling is optional, and a field the format does not name is refused, so a misspelt one never reads as absent. Its canonical text is its RFC 8785 form, and the BLAKE3 of that text, the target's hash, names the snapshot in a receipt.", + "type": "object", + "required": [ + "format", + "name", + "source", + "qubits", + "gates", + "coupling" + ], + "additionalProperties": false, + "properties": { + "format": { + "const": "wai.quantum.target/1" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 200 + }, + "source": { + "type": "object", + "required": [ + "format" + ], + "additionalProperties": false, + "properties": { + "format": { + "type": "string", + "description": "The format the target was read from (wai-quantum targets import --help lists them)." + }, + "note": { + "type": "string", + "maxLength": 400 + } + } + }, + "calibration": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "maxLength": 400, + "description": "The calibration snapshot's id, as the source names it, or a content id of the snapshot read." + }, + "timestamp": { + "type": "string", + "maxLength": 400, + "description": "When the snapshot was taken, as the source writes it." + } + } + }, + "qubits": { + "type": "array", + "minItems": 1, + "maxItems": 2048, + "description": "Every qubit, in order.", + "items": { + "type": "object", + "required": [ + "qubit" + ], + "additionalProperties": false, + "properties": { + "qubit": { + "type": "integer", + "minimum": 0, + "description": "Its index: its place in the list." + }, + "label": { + "type": "string", + "description": "The source's own name for it, when that is not its index." + }, + "t1_us": { + "type": "number", + "minimum": 0, + "description": "T1, microseconds." + }, + "t2_us": { + "type": "number", + "minimum": 0, + "description": "T2 (the echo or Ramsey time the source reports), microseconds." + }, + "frequency_ghz": { + "type": "number", + "minimum": 0, + "description": "Its frequency, gigahertz." + }, + "readout": { + "type": "object", + "required": [ + "p01", + "p10" + ], + "additionalProperties": false, + "properties": { + "p01": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "P(reads 1 | holds 0)." + }, + "p10": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "P(reads 0 | holds 1)." + } + } + }, + "measure_ns": { + "type": "number", + "minimum": 0, + "description": "The measurement's duration, nanoseconds." + } + } + } + }, + "gates": { + "type": "array", + "maxItems": 262144, + "description": "Each native gate where the device runs it, sorted by gate then qubits.", + "items": { + "type": "object", + "required": [ + "gate", + "qubits" + ], + "additionalProperties": false, + "properties": { + "gate": { + "type": "string", + "pattern": "^[a-z0-9_]{1,40}$" + }, + "qubits": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "items": { + "type": "integer", + "minimum": 0 + } + }, + "error": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "The average gate infidelity." + }, + "duration_ns": { + "type": "number", + "minimum": 0, + "description": "Nanoseconds." + } + } + } + }, + "coupling": { + "type": "array", + "description": "The pairs a two-qubit gate may act on, each once, the lower qubit first, sorted.", + "items": { + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": { + "type": "integer", + "minimum": 0 + } + } + } + } + } + ] + }, + "fabric": { + "description": "Where the statevector method's state runs: auto (the default: on a member only where the committed measurements show it faster than this host's CPU for the job's size and fusion width, otherwise on the CPU), cpu, accelerator (the first accelerator member certified bit-exact here that holds the state, falling back to the next if it fails during the run), a member's id or key (wai-quantum fabric lists them), or a list of members, a power of two of them, the state split by its top qubits into one partition on each (cpu is a member, and a member may be named more than once). A member certified bit-exact gives the CPU's bits. A placement this host cannot honour is refused (J013), never made elsewhere.", + "anyOf": [ + { + "type": "string", + "minLength": 1 + }, + { + "type": "array", + "minItems": 2, + "maxItems": 64, + "items": { + "type": "string", + "minLength": 1 + } + } + ] + }, + "repair": { + "description": "Repair the program first on its flagged lines: true, or the choices.", + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "properties": { + "max_iterations": { + "type": "integer", + "minimum": 1 + }, + "dyadic_bits": { + "type": "integer", + "minimum": 1, + "maximum": 32 + }, + "sizes": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + } + } + } + ] + }, + "history": { + "type": "object", + "description": "The program's history's account of the version the job runs: its digest, and the gates and lines in each hand. The receipt binds it; a history recomputes and checks it." + }, + "provider": { + "type": "string", + "description": "The person's own provider to run on, by the name their registry gives it. Only a host that holds their credentials runs such a job; every other host refuses it." + }, + "programs": { + "type": "array", + "minItems": 1, + "items": { + "anyOf": [ + { + "type": "string", + "description": "A program's text." + }, + { + "type": "object", + "required": [ + "qasm" + ], + "description": "A job of its own, read as a job request is (no programs or sweep in it); each item of the set's result holds its request in full." + } + ] + }, + "description": "A set (engine::sets): the programs to run as one job, each a program's text or a job of its own; the request's other fields apply to every item that does not set them itself." + }, + "sweep": { + "type": "object", + "additionalProperties": { + "type": "array", + "minItems": 1, + "items": { + "type": "number" + } + }, + "description": "A set over the request's own qasm: values for each of the program's inputs (integer, float or angle), every combination run, the names in sorted order and the first varying slowest." + }, + "params": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "A value for each of the program's parameters (`input float theta;`, `input angle phi;`), bound exactly before the program is read: it runs as if each were written as a `const` at that double. A parameter left without a value is refused (Q114, J050). In a sweep, the parameters it fixes, each bound at every point." + }, + "dry_run": { + "type": "boolean", + "description": "With true: what the host would do with the job or set, running nothing." + }, + "mitigate": { + "description": "Mitigate the job's expectation values (or, for readout, its counts) under its noise (engine::mitigate): zne, pea, pec, cdr, vd or readout, or {\"method\", …} with its options. The result's mitigation gives each value raw and mitigated.", + "anyOf": [ + { + "enum": [ + "zne", + "pea", + "pec", + "cdr", + "vd", + "readout" + ] + }, + { + "type": "object", + "required": [ + "method" + ] + } + ] + }, + "pulse": { + "type": "object", + "description": "A pulse run's options (method \"pulse\"): the sample period, the levels kept, the tolerance on the stated error, the steps a sample is divided into, each qubit's parameters, static couplings, and ports beyond the names d0, m0, a0.", + "additionalProperties": false, + "properties": { + "dt_ns": { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 1000, + "description": "The sample period, ns (default 0.5)." + }, + "levels": { + "type": "integer", + "enum": [ + 2, + 3 + ], + "description": "Levels kept per qubit (default 2; 3 shows leakage)." + }, + "tolerance": { + "type": "number", + "exclusiveMinimum": 0, + "exclusiveMaximum": 1, + "description": "The most the stated error may be (default 1e-6): a run whose bound and rounding estimate pass it is refused, naming the steps that would meet it." + }, + "substeps": { + "type": "integer", + "minimum": 1, + "maximum": 4096, + "description": "Steps per sample (default: chosen so each step times the generator's norm is at most 0.5)." + }, + "qubits": { + "type": "object", + "description": "Each qubit's parameters by its index, over the target's and the defaults.", + "additionalProperties": { + "type": "object", + "additionalProperties": false, + "properties": { + "frequency_ghz": { + "type": "number", + "description": "Its frequency, GHz." + }, + "rabi_mhz": { + "type": "number", + "description": "Its Rabi frequency at full amplitude, MHz." + }, + "anharmonicity_mhz": { + "type": "number", + "description": "Its anharmonicity, MHz." + }, + "t1_us": { + "type": "number", + "description": "Its relaxation time, µs." + }, + "t2_us": { + "type": "number", + "description": "Its coherence time, µs (at most 2·T1)." + } + } + } + }, + "couplings": { + "type": "array", + "description": "Static ZZ couplings.", + "items": { + "type": "object", + "required": [ + "qubits", + "zz_khz" + ], + "additionalProperties": false, + "properties": { + "qubits": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 2, + "maxItems": 2 + }, + "zz_khz": { + "type": "number", + "description": "The coupling's rate, kHz." + } + } + } + }, + "ports": { + "type": "object", + "description": "Ports by name: what each is for and the qubit it reaches.", + "additionalProperties": { + "type": "object", + "required": [ + "kind", + "qubit" + ], + "additionalProperties": false, + "properties": { + "kind": { + "enum": [ + "drive", + "measure", + "acquire" + ] + }, + "qubit": { + "type": "integer", + "minimum": 0 + } + } + } + } + } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } + } + } + }, + "result": { + "title": "wai.quantum.job-result/1", + "description": "A job's result as the engine gives it, on every host: what was asked of the program, computed by the method its plan chose, with that method's accuracy class. The receipt seals the result without its receipt member, beside the request. A result names the engine that made it and this schema (engine and schema); results made before results carried them have neither and follow this schema all the same.", + "type": "object", + "required": [ + "method", + "qubits", + "gates", + "accuracy" + ], + "properties": { + "engine": { + "type": "object", + "description": "The engine that made the result: the wai-quantum crate's name and version.", + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "const": "wai-quantum" + }, + "version": { + "type": "string", + "description": "Its semantic version, as MAJOR.MINOR.PATCH." + } + } + }, + "schema": { + "const": "wai.quantum.job-result/1", + "description": "The schema the result follows." + }, + "components": { + "type": "array", + "description": "The identity of every component that made the result, when a registered one took part (engine::registry): its program's format, the passes its compile ran, the noise channels it names, its method; each registered one marked so. Sealed by the receipt with the rest.", + "items": { + "type": "object", + "description": "One component that made the result (engine::registry): its kind, name and version, the BLAKE3 digest of its descriptor, and whether it is built in. A result carries these only when a registered component took part; one made by built-ins alone names them as it always has (its method, its compile's passes, its noise's channels and the engine's version), the digests of that version listed by the components list.", + "required": [ + "kind", + "name", + "version", + "digest", + "origin" + ], + "properties": { + "kind": { + "enum": [ + "method", + "pass", + "channel", + "front_end" + ] + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "digest": { + "type": "string", + "pattern": "^[0-9a-f]{64}$", + "description": "BLAKE3 of the component's descriptor in its canonical JSON (engine::registry::digest_of)." + }, + "origin": { + "enum": [ + "built-in", + "registered" + ], + "description": "built-in: the engine's own; registered: a host's own, added in its process, not part of the engine." + }, + "certified": { + "const": false, + "description": "Beside a registered component: the engine does not certify it." + } + } + } + }, + "method": { + "type": "string", + "description": "The method that ran the job (provider for a run on the person's own provider)." + }, + "qubits": { + "type": "integer", + "minimum": 0 + }, + "gates": { + "type": "integer", + "minimum": 0, + "description": "The program's gates, in standard gates (at most 2^53 - 1), however the method ran them." + }, + "operations": { + "type": "integer", + "minimum": 0, + "description": "When the method held a gate under many controls as one (statevector, and exact asked for it): the operations it ran." + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "state_hash": { + "type": "string", + "description": "The bit-exact method's statevector hash (BLAKE3, hex): the same on every machine." + }, + "counts": { + "type": "object", + "description": "Outcomes and their counts, keyed by the program's classical bits, the highest bit first. At most 65536 outcomes are listed; omitted_shots holds the rest.", + "additionalProperties": { + "type": "integer", + "minimum": 0 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "outcome_dimension": { + "type": "integer", + "minimum": 0, + "description": "The stabilizer method: the dimension of the measured outcomes' affine space." + }, + "shots": { + "type": "integer", + "minimum": 0, + "description": "The shots, where the method names them in the result (trajectories, provider)." + }, + "expectations": { + "type": "array", + "items": { + "type": "object", + "required": [ + "observable", + "coeff", + "value" + ], + "properties": { + "observable": { + "type": "string" + }, + "coeff": { + "type": "number" + }, + "value": { + "type": "number", + "description": "The coefficient times the expectation value." + }, + "stderr": { + "type": "number", + "description": "The standard error, for an estimate." + }, + "bound": { + "type": "number", + "description": "A bound on |exact − value|: rigorous for the bounded class; with confidence beside it, holding with that probability." + }, + "peak_terms": { + "type": "integer" + }, + "threshold_reached": { + "type": "number" + }, + "max_terms": { + "type": "integer" + }, + "ladder": { + "type": "array", + "description": "The value at thresholds a decade apart, the asked one last.", + "items": { + "type": "object", + "required": [ + "threshold", + "value", + "bound" + ], + "properties": { + "threshold": { + "type": "number" + }, + "value": { + "type": "number" + }, + "bound": { + "type": "number" + }, + "peak_terms": { + "type": "integer" + }, + "threshold_reached": { + "type": "number" + } + } + } + }, + "confidence": { + "type": "number", + "description": "The probability the bound holds, for a bound that holds with a stated probability (stabilizer_rank's sampled mode)." + } + } + } + }, + "amplitudes": { + "type": "array", + "items": { + "type": "object", + "required": [ + "bits", + "re", + "im" + ], + "properties": { + "bits": { + "type": "string", + "description": "One 0 or 1 per qubit, qubit n-1 first." + }, + "re": { + "type": "number" + }, + "im": { + "type": "number" + }, + "bound": { + "type": "number", + "minimum": 0, + "description": "A bound on |exact − value| of the amplitude, holding with the probability confidence states (stabilizer_rank's sampled mode)." + }, + "confidence": { + "type": "number", + "description": "The probability the bound holds." + } + } + } + }, + "global_phase": { + "type": "string", + "description": "Why the amplitudes' global phase is not fixed, when it is not." + }, + "warning": { + "type": "string" + }, + "contraction_flops": { + "type": "number", + "description": "The tensor network's contraction cost." + }, + "dynamic": { + "type": "object", + "description": "A program that measures in the middle, resets or branches on a measured bit: how it ran.", + "properties": { + "measurements_and_resets": { + "type": "integer", + "minimum": 0 + }, + "branches_run": { + "type": "integer", + "minimum": 0 + }, + "states_at_once": { + "type": "integer", + "minimum": 0 + }, + "branches_weighed": { + "type": "integer", + "minimum": 0 + } + } + }, + "outputs": { + "type": "array", + "description": "The program's output declarations: each its name and type, and its value, or the places of its bits in each outcome.", + "items": { + "type": "object", + "required": [ + "name", + "type" + ], + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "bits": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "value": { + "description": "A number, a boolean, a bit string, a duration's text, {\"re\", \"im\"}, or an array of them." + } + } + } + }, + "timing": { + "type": "object", + "description": "A program that states durations (delay, box, stretch) the method does not apply: said so, with the reader's code.", + "required": [ + "applied", + "why" + ], + "properties": { + "applied": { + "type": "boolean" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "diagnostics": { + "type": "array", + "description": "The reader's warnings and notes on the program, each with its code.", + "items": { + "type": "object", + "description": "One of the reader's diagnostics: its code, what happens to the construct it is about, its message (without the line or the code), and where it stands.", + "required": [ + "code", + "outcome", + "message" + ], + "properties": { + "code": { + "type": "string" + }, + "outcome": { + "enum": [ + "refused", + "lowered", + "carried", + "preserved", + "warned" + ] + }, + "message": { + "type": "string" + }, + "line": { + "type": "integer", + "minimum": 1 + }, + "column": { + "type": "integer", + "minimum": 1 + }, + "length": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "compiled": { + "description": "How the program was compiled before it ran: on the person's own provider, to the device's gates; or, asked with compile, to a basis within a budget. Either way, basis is the gate set it was compiled to.", + "anyOf": [ + { + "type": "object", + "description": "A provider job: the program sent, compiled exactly to the device's own gates: its basis (the device's gate set), its OpenQASM 3 text (qasm3) and that text's BLAKE3 (program), its counts of gates and swaps, its layouts, and the check it passed before it was sent. Results sealed before qasm3 carry the hash alone.", + "required": [ + "basis", + "program" + ], + "properties": { + "basis": { + "type": "string" + }, + "program": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "qasm3": { + "type": "string", + "description": "The program sent, as OpenQASM 3, $i being index i of the coupling map the provider described; program is the BLAKE3 of its UTF-8 bytes." + }, + "qubit_names": { + "type": "object", + "additionalProperties": { + "type": "string", + "minLength": 1 + }, + "description": "The device's own name for each index the program uses, as it was when the job was sent, where a client sends it under those names." + }, + "native_gates": { + "type": "integer" + }, + "two_qubit_gates": { + "type": "integer" + }, + "swaps": { + "type": "integer" + }, + "layout": { + "type": "array", + "items": { + "type": "integer" + } + }, + "final_layout": { + "type": "array", + "items": { + "type": "integer" + } + }, + "checked": { + "type": "string" + }, + "placement": { + "type": "object", + "description": "Where the program was placed on the device's qubits, and why." + } + } + }, + { + "type": "object", + "description": "A job asked to compile its program first: what ran is the compiled circuit, within distance of the program in the operator norm up to a global phase.", + "required": [ + "basis", + "verdict" + ], + "properties": { + "basis": { + "enum": [ + "clifford_t", + "standard" + ], + "description": "The gate set the program was compiled to." + }, + "level": { + "type": "integer", + "minimum": 0 + }, + "epsilon": { + "type": "number", + "description": "The budget asked for." + }, + "distance": { + "type": [ + "number", + "null" + ], + "description": "The bound the passes' distances add to." + }, + "verdict": { + "type": "string" + }, + "source": { + "type": "object", + "description": "A circuit's counts, as the compiler counts them.", + "properties": { + "gates": { + "type": "integer", + "minimum": 0 + }, + "one_qubit": { + "type": "integer", + "minimum": 0 + }, + "two_qubit": { + "type": "integer", + "minimum": 0 + }, + "three_qubit": { + "type": "integer", + "minimum": 0 + }, + "cnots": { + "type": "integer", + "minimum": 0 + }, + "t_count": { + "type": "integer", + "minimum": 0 + }, + "rotations": { + "type": "integer", + "minimum": 0 + }, + "depth": { + "type": "integer", + "minimum": 0 + } + } + }, + "output": { + "type": "object", + "description": "A circuit's counts, as the compiler counts them.", + "properties": { + "gates": { + "type": "integer", + "minimum": 0 + }, + "one_qubit": { + "type": "integer", + "minimum": 0 + }, + "two_qubit": { + "type": "integer", + "minimum": 0 + }, + "three_qubit": { + "type": "integer", + "minimum": 0 + }, + "cnots": { + "type": "integer", + "minimum": 0 + }, + "t_count": { + "type": "integer", + "minimum": 0 + }, + "rotations": { + "type": "integer", + "minimum": 0 + }, + "depth": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": [ + "string", + "null" + ], + "description": "The BLAKE3 of the compile certificate's RFC 8785 text, in hex." + }, + "note": { + "type": "string" + } + } + } + ] + }, + "verdict": { + "title": "wai.quantum.verdict/1", + "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", + "type": "object", + "required": [ + "schema", + "level", + "rank", + "holds", + "statement", + "parsed", + "executed", + "intent", + "critique", + "repairs" + ], + "properties": { + "schema": { + "const": "wai.quantum.verdict/1" + }, + "level": { + "enum": [ + "refused", + "parsed", + "executed", + "evidence", + "proof" + ] + }, + "rank": { + "type": "integer", + "minimum": 0, + "maximum": 4, + "description": "The level's place on the ladder, from 0 (refused) to 4 (proof)." + }, + "holds": { + "type": [ + "boolean", + "null" + ] + }, + "statement": { + "type": "string", + "description": "The level in one plain line." + }, + "parsed": { + "type": "object", + "description": "Whether the reader took the program, and its warnings and notes with their codes, or its refusal.", + "required": [ + "ok" + ], + "properties": { + "ok": { + "type": "boolean" + }, + "diagnostics": { + "type": "array", + "items": { + "type": "object", + "description": "One of the reader's diagnostics: its code, what happens to the construct it is about, its message (without the line or the code), and where it stands.", + "required": [ + "code", + "outcome", + "message" + ], + "properties": { + "code": { + "type": "string" + }, + "outcome": { + "enum": [ + "refused", + "lowered", + "carried", + "preserved", + "warned" + ] + }, + "message": { + "type": "string" + }, + "line": { + "type": "integer", + "minimum": 1 + }, + "column": { + "type": "integer", + "minimum": 1 + }, + "length": { + "type": "integer", + "minimum": 0 + } + } + } + }, + "code": { + "type": "string" + }, + "outcome": { + "enum": [ + "refused", + "retry", + "failed", + "lowered", + "carried", + "preserved", + "warned", + "dropped", + "defaulted" + ] + }, + "message": { + "type": "string" + }, + "line": { + "type": "integer", + "minimum": 1 + }, + "column": { + "type": "integer", + "minimum": 1 + }, + "length": { + "type": "integer", + "minimum": 0 + }, + "text": { + "type": "string", + "description": "The refusal as the reader wrote it, with its line and code." + } + } + }, + "executed": { + "type": [ + "object", + "null" + ], + "description": "The method that ran and its accuracy class, and the distance a compile put between the program and what ran.", + "properties": { + "method": { + "type": "string" + }, + "accuracy": { + "type": [ + "string", + "null" + ] + }, + "compiled_distance": { + "type": [ + "number", + "null" + ] + } + } + }, + "intent": { + "type": "array", + "items": { + "type": "object", + "description": "One intent's check: what it asked, whether it held, how strong the check was and how it was made.", + "required": [ + "kind", + "outcome", + "strength", + "how" + ], + "properties": { + "kind": { + "enum": [ + "distribution", + "equivalent", + "prepares", + "sampled", + "compiled" + ] + }, + "outcome": { + "enum": [ + "holds", + "fails", + "unchecked" + ] + }, + "strength": { + "enum": [ + "proof", + "evidence", + "none" + ] + }, + "how": { + "type": "string" + }, + "why": { + "type": "string" + }, + "distance": { + "type": "number" + }, + "tolerance": { + "type": "number" + }, + "outcomes": { + "type": "integer", + "description": "The outcomes the distribution holds, or the samples' distinct outcomes." + }, + "distribution": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "The program's distribution, when its outcomes are few enough to list." + }, + "largest_gaps": { + "type": "array", + "items": { + "type": "object", + "properties": { + "outcome": { + "type": "string" + }, + "program": { + "type": "number" + }, + "intent": { + "type": "number" + } + } + } + }, + "global_phase": { + "type": [ + "number", + "null" + ] + }, + "method": { + "type": "string", + "description": "A sampled intent: the method the samples were run by." + }, + "seed": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "alpha": { + "type": "number" + }, + "fit": { + "type": "object", + "description": "A sampled intent: the test, its statistic, degrees of freedom and p-value, the level, and whether it rejected.", + "properties": { + "test": { + "type": "string" + }, + "statistic": { + "type": "number" + }, + "dof": { + "type": "integer" + }, + "p_value": { + "type": "number" + }, + "alpha": { + "type": "number" + }, + "shots": { + "type": "integer" + }, + "rejected": { + "type": "boolean" + }, + "smallest_expected": { + "type": [ + "number", + "null" + ] + }, + "impossible": { + "type": [ + "integer", + "array", + "boolean" + ] + }, + "note": { + "type": "string" + } + } + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + }, + "name": { + "type": "string" + }, + "note": { + "type": "string" + } + } + } + }, + "critique": { + "type": "array", + "description": "The program's smells, each with its lines.", + "items": { + "type": "object" + } + }, + "repairs": { + "type": "array", + "description": "Each edit a repair made, with the code it answered and the lines it changed.", + "items": { + "type": "object" + } + }, + "refusal": { + "type": "object", + "description": "For a refused job: its message and its codes.", + "properties": { + "message": { + "type": "string" + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "codes": { + "type": "array", + "items": { + "type": "string" + } + }, + "outcome": { + "enum": [ + "refused", + "retry", + "failed", + "lowered", + "carried", + "preserved", + "warned", + "dropped", + "defaulted" + ] + }, + "meaning": { + "type": "string" + } + } + }, + "sealed": { + "type": "boolean" + } + } + }, + "target": { + "type": "object", + "description": "A run on a device target: which target (its hash, as its receipt binds it), its calibration snapshot, where the program was placed and why, and the noise derived from the target.", + "required": [ + "name", + "hash" + ], + "properties": { + "name": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "hash_is": { + "type": "string" + }, + "calibration": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + } + }, + "source": { + "type": "object", + "properties": { + "format": { + "type": "string" + }, + "note": { + "type": "string" + } + } + }, + "placement": { + "type": "object", + "description": "The native gate set, the layout and routes chosen, the swaps, the expected success beside the fewest-swaps layout's, and the check of the compiled program." + }, + "noise": { + "type": "object", + "description": "The noise model derived from the target's calibration: its channels, durations and idling, and each qubit's readout." + } + } + }, + "fabric": { + "type": "object", + "description": "Where the state vector, or the pauli method's sum of terms, ran: the kernel, the placement the job asked for, the member that ran it (or each partition's), each with its certificate, and the energy. Present when the job asked for a placement, or when auto placed the state on a member by measurement (`auto`); a job auto leaves on the CPU names nothing; the receipt seals it with the rest of the result. Every member placed is certified bit-exact, so the answers are the CPU's, byte for byte.", + "required": [ + "kernel", + "asked", + "parity", + "energy" + ], + "properties": { + "kernel": { + "type": "string" + }, + "asked": { + "description": "The placement the job asked for, as it gave it.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "member": { + "type": "string" + }, + "key": { + "type": "string" + }, + "class": { + "type": "string" + }, + "implementation": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "wide": { + "type": "object", + "description": "A member's certificate for gates on more than three qubits at once (wai.quantum.sv/run-wide): a fusion width of 4 to 6, or a wider gate, runs kernels the pinned corpus does not reach, certified on a corpus of their own (sv64-wide-v1). A member is placed for such a job only when this certificate is bit-exact; one that is not, or has none, says why and runs only gates on up to three qubits at once.", + "required": [ + "parity" + ], + "properties": { + "kernel": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "why": { + "type": "string" + } + } + }, + "partitions": { + "type": "array", + "description": "Each partition's member, by the value of the state's top qubits: partition i holds the amplitudes whose top bits read i.", + "items": { + "type": "object", + "description": "A member of the fabric and its certificate for the kernel: its id (which binds the device), its key, its class, the implementation, the parity tier, the certificate's digest (BLAKE3, hex), and the corpus it was earned on (its digest, generator and cases; the CPU reference's own standing has none).", + "required": [ + "member", + "implementation", + "parity", + "certificate" + ], + "properties": { + "member": { + "type": "string" + }, + "key": { + "type": "string" + }, + "class": { + "type": "string" + }, + "implementation": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "wide": { + "type": "object", + "description": "A member's certificate for gates on more than three qubits at once (wai.quantum.sv/run-wide): a fusion width of 4 to 6, or a wider gate, runs kernels the pinned corpus does not reach, certified on a corpus of their own (sv64-wide-v1). A member is placed for such a job only when this certificate is bit-exact; one that is not, or has none, says why and runs only gates on up to three qubits at once.", + "required": [ + "parity" + ], + "properties": { + "kernel": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "why": { + "type": "string" + } + } + }, + "why": { + "type": "string", + "description": "For a member the job fell back from: how it failed." + } + } + } + }, + "partition_qubits": { + "type": "integer", + "minimum": 0 + }, + "local_qubits": { + "type": "integer", + "minimum": 0 + }, + "segments": { + "type": "integer", + "minimum": 0, + "description": "Runs of gates the partitions took in turn, between exchanges." + }, + "exchanges": { + "type": "integer", + "minimum": 0, + "description": "Partition qubits exchanged with local ones through the host's copy of the state." + }, + "fell_back_from": { + "type": "array", + "description": "An accelerator request whose member failed during the run: each member that failed, in turn, with how; the member named above ran the job.", + "items": { + "type": "object", + "description": "A member of the fabric and its certificate for the kernel: its id (which binds the device), its key, its class, the implementation, the parity tier, the certificate's digest (BLAKE3, hex), and the corpus it was earned on (its digest, generator and cases; the CPU reference's own standing has none).", + "required": [ + "member", + "implementation", + "parity", + "certificate" + ], + "properties": { + "member": { + "type": "string" + }, + "key": { + "type": "string" + }, + "class": { + "type": "string" + }, + "implementation": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "wide": { + "type": "object", + "description": "A member's certificate for gates on more than three qubits at once (wai.quantum.sv/run-wide): a fusion width of 4 to 6, or a wider gate, runs kernels the pinned corpus does not reach, certified on a corpus of their own (sv64-wide-v1). A member is placed for such a job only when this certificate is bit-exact; one that is not, or has none, says why and runs only gates on up to three qubits at once.", + "required": [ + "parity" + ], + "properties": { + "kernel": { + "type": "string" + }, + "parity": { + "type": "object", + "description": "A certificate's standing against the CPU reference: bit-exact, within a bound (max_ulp, max_abs), statistical (fidelity over shots) or uncertified. Only bit-exact members are placed.", + "required": [ + "tier" + ], + "properties": { + "tier": { + "enum": [ + "bit-exact", + "within", + "statistical", + "uncertified" + ] + }, + "max_ulp": { + "type": "integer", + "minimum": 0 + }, + "max_abs": { + "type": "number" + }, + "fidelity": { + "type": "number" + }, + "shots": { + "type": "integer", + "minimum": 0 + } + } + }, + "certificate": { + "type": "string" + }, + "corpus": { + "type": "string" + }, + "generator": { + "type": "string" + }, + "cases": { + "type": "integer", + "minimum": 0 + }, + "why": { + "type": "string" + } + } + }, + "why": { + "type": "string", + "description": "For a member the job fell back from: how it failed." + } + } + } + }, + "auto": { + "type": "object", + "description": "Why auto placed the state where it ran: the rule (a member is placed only where the committed measurements show it faster than this host's CPU for the job's size and fusion width) and the measured row it rests on, with the host, the day and the load it was measured under. Present only when auto placed a state on a member.", + "required": [ + "rule", + "host", + "fusion", + "from_qubits", + "to_qubits" + ], + "properties": { + "rule": { + "type": "string" + }, + "host": { + "type": "string", + "description": "The host's processor as the measurements name it (cpu--)." + }, + "measured": { + "type": "string", + "description": "The day the host was measured (UTC)." + }, + "about": { + "type": "string" + }, + "load": { + "type": "string" + }, + "discovery_ms": { + "type": "number", + "description": "What discovering and certifying the host's members took, once per process, as measured." + }, + "fusion": { + "type": "integer", + "minimum": 1 + }, + "from_qubits": { + "type": "integer", + "minimum": 0 + }, + "to_qubits": { + "type": "integer", + "minimum": 0 + }, + "min_launches": { + "type": "integer", + "minimum": 0 + }, + "basis": { + "type": "object", + "description": "The measured row the job is judged by: the largest measured size at or below its own, the launches of its plan, the runs of each, and the spread of the CPU's and the member's times in milliseconds.", + "required": [ + "qubits", + "launches", + "runs", + "cpu_ms", + "member_ms" + ], + "properties": { + "qubits": { + "type": "integer", + "minimum": 0 + }, + "launches": { + "type": "integer", + "minimum": 0 + }, + "runs": { + "type": "integer", + "minimum": 0 + }, + "cpu_ms": { + "type": "object", + "description": "The least, the median and the most of a measured row's runs, in milliseconds.", + "required": [ + "min", + "median", + "max" + ], + "properties": { + "min": { + "type": "number" + }, + "median": { + "type": "number" + }, + "max": { + "type": "number" + } + } + }, + "member_ms": { + "type": "object", + "description": "The least, the median and the most of a measured row's runs, in milliseconds.", + "required": [ + "min", + "median", + "max" + ], + "properties": { + "min": { + "type": "number" + }, + "median": { + "type": "number" + }, + "max": { + "type": "number" + } + } + } + } + } + } + }, + "energy": { + "description": "The CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or unmetered with the reason.", + "anyOf": [ + { + "type": "object", + "required": [ + "unmetered" + ], + "properties": { + "unmetered": { + "type": "string" + }, + "service_kwh": { + "type": "number", + "description": "A provider job: the provider's own figure." + }, + "service_kwh_is": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "joules_micro", + "energy_provenance", + "coverage" + ], + "properties": { + "joules_micro": { + "type": "integer", + "minimum": 1 + }, + "energy_provenance": { + "type": "string" + }, + "energy_uncertainty": { + "type": "object", + "properties": { + "relative_ppm": { + "type": "integer" + }, + "window_us": { + "type": "integer" + } + } + }, + "energy_counter_filtering": { + "type": "string" + }, + "coverage": { + "enum": [ + "whole", + "partial" + ] + }, + "covers": { + "type": "string" + }, + "excludes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpu_ms": { + "type": "integer" + }, + "source": { + "type": "string" + }, + "attribution": { + "enum": [ + "process", + "none" + ], + "description": "Whose energy it is: the job's worker process, or none (the processor packages' over the job's window, every process on the host in it)." + }, + "packages": { + "type": "integer", + "minimum": 1, + "description": "The processor packages read." + }, + "concurrent_jobs": { + "type": "integer", + "minimum": 0, + "description": "Other jobs that ran on the host during the window." + }, + "counter": { + "type": "object", + "description": "The package counter as seen: the longest it went between updates, and the smallest step it took.", + "properties": { + "update_us": { + "type": "integer", + "minimum": 0 + }, + "step_uj": { + "type": "integer", + "minimum": 0 + } + } + }, + "declared": { + "type": "string", + "description": "What the stated uncertainty covers, and what it does not." + } + } + } + ] + }, + "why": { + "type": "string" + } + } + }, + "repaired": { + "type": "object", + "description": "A job asked to repair its program first: the program that ran, each repair, and what needs a person.", + "properties": { + "qasm": { + "type": "string" + }, + "repairs": { + "type": "array", + "items": { + "type": "object", + "required": [ + "code", + "by", + "edits" + ], + "properties": { + "code": { + "type": "string" + }, + "rule": { + "type": "string" + }, + "by": { + "enum": [ + "engine", + "proposal" + ] + }, + "flagged": { + "type": "array", + "items": { + "type": "integer" + } + }, + "edits": { + "type": "array", + "items": { + "type": "object", + "properties": { + "line": { + "type": "integer" + }, + "before": { + "type": [ + "string", + "null" + ] + }, + "after": { + "type": [ + "string", + "null" + ] + } + } + } + } + } + } + }, + "needs_person": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0, + "description": "Wall time of the run, where the host has a clock (not in a browser tab)." + }, + "energy": { + "description": "The CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or unmetered with the reason.", + "anyOf": [ + { + "type": "object", + "required": [ + "unmetered" + ], + "properties": { + "unmetered": { + "type": "string" + }, + "service_kwh": { + "type": "number", + "description": "A provider job: the provider's own figure." + }, + "service_kwh_is": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "joules_micro", + "energy_provenance", + "coverage" + ], + "properties": { + "joules_micro": { + "type": "integer", + "minimum": 1 + }, + "energy_provenance": { + "type": "string" + }, + "energy_uncertainty": { + "type": "object", + "properties": { + "relative_ppm": { + "type": "integer" + }, + "window_us": { + "type": "integer" + } + } + }, + "energy_counter_filtering": { + "type": "string" + }, + "coverage": { + "enum": [ + "whole", + "partial" + ] + }, + "covers": { + "type": "string" + }, + "excludes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cpu_ms": { + "type": "integer" + }, + "source": { + "type": "string" + }, + "attribution": { + "enum": [ + "process", + "none" + ], + "description": "Whose energy it is: the job's worker process, or none (the processor packages' over the job's window, every process on the host in it)." + }, + "packages": { + "type": "integer", + "minimum": 1, + "description": "The processor packages read." + }, + "concurrent_jobs": { + "type": "integer", + "minimum": 0, + "description": "Other jobs that ran on the host during the window." + }, + "counter": { + "type": "object", + "description": "The package counter as seen: the longest it went between updates, and the smallest step it took.", + "properties": { + "update_us": { + "type": "integer", + "minimum": 0 + }, + "step_uj": { + "type": "integer", + "minimum": 0 + } + } + }, + "declared": { + "type": "string", + "description": "What the stated uncertainty covers, and what it does not." + } + } + } + ] + }, + "receipt": { + "anyOf": [ + { + "title": "wai.quantum.receipt/2", + "description": "A result's receipt: an Ed25519 signature, by the key it names, over digest = BLAKE3(\"wai:quantum-service-receipt\\x02\" ‖ len ‖ request ‖ len ‖ result), each of request and result in its RFC 8785 canonical text (the result without its receipt member), each length 8 bytes big-endian. Whatever members the request and the result hold are sealed, the result's engine and schema among them. The first receipts (no canon member, $defs/first) sealed their writer's compact text under the domain ending \\x01; they still verify. wai/extensions/quantum-providers.md section 8.2 states the seal in full, and section 8.4 what a verifier checks.", + "type": "object", + "required": [ + "alg", + "canon", + "key", + "digest", + "signature" + ], + "properties": { + "alg": { + "const": "ed25519" + }, + "canon": { + "const": "rfc8785", + "description": "The canonical form the digest is taken over." + }, + "key": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$", + "description": "The signing key, 32 bytes in lower-case hex." + }, + "digest": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$", + "description": "The digest signed, 32 bytes in lower-case hex." + }, + "signature": { + "type": "string", + "minLength": 128, + "maxLength": 128, + "pattern": "^[0-9a-f]{128}$", + "description": "The signature, 64 bytes in lower-case hex." + } + } + }, + { + "description": "The first form, before canon: the digest is over the compact text its writer wrote of each, members in the document's order (section 8.2 of wai/extensions/quantum-providers.md), under the domain ending \\x01. Never written now; still verified.", + "type": "object", + "required": [ + "alg", + "key", + "digest", + "signature" + ], + "properties": { + "alg": { + "const": "ed25519" + }, + "key": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$" + }, + "digest": { + "type": "string", + "minLength": 64, + "maxLength": 64, + "pattern": "^[0-9a-f]{64}$" + }, + "signature": { + "type": "string", + "minLength": 128, + "maxLength": 128, + "pattern": "^[0-9a-f]{128}$" + } + } + } + ] + }, + "provider": { + "type": "object", + "description": "A provider job: the provider's name, kind and protocol, the device, its provenance, and the hash of its description." + }, + "counts_source": { + "enum": [ + "shots", + "vendor_counts", + "probabilities" + ], + "description": "A provider job: where its counts come from (wai/extensions/quantum-providers.md section 8.3): tallied from one record a shot (shots), the provider's own counts (vendor_counts), or rebuilt from the probabilities it returned by largest remainders, derived and not shot records (probabilities). Results sealed before it carry neither it nor execution." + }, + "execution": { + "type": "object", + "description": "A provider job: how the device was asked to run the program (section 8.3): who states it (stated_by: client, provider or nobody); what the client sent (sent: the request's members and the settings among them); each of mitigation, twirling, decoupling, remapping and optimisation (off, on, default when the request sets nothing for it, none when the device has no such step, unknown when nobody states it); whether the gates were to run as written (verbatim); and a note.", + "required": [ + "stated_by", + "mitigation", + "twirling", + "decoupling", + "remapping", + "optimisation", + "verbatim" + ], + "properties": { + "stated_by": { + "enum": [ + "client", + "provider", + "nobody" + ] + }, + "sent": { + "type": "object", + "required": [ + "fields", + "settings" + ], + "properties": { + "fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "settings": { + "type": "object" + } + }, + "additionalProperties": false + }, + "mitigation": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "twirling": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "decoupling": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "remapping": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "optimisation": { + "enum": [ + "off", + "on", + "default", + "none", + "unknown" + ], + "description": "What happened to one step: off or on (by a setting the client sent, or as the provider states), default (the request sets nothing for it, so the provider's default stands), none (the device has no such step), unknown (nobody states it)." + }, + "verbatim": { + "type": [ + "boolean", + "null" + ] + }, + "note": { + "type": "string" + } + }, + "additionalProperties": false + }, + "calibration": { + "type": [ + "string", + "null" + ], + "description": "A provider job: the calibration snapshot it ran under." + }, + "job": { + "type": "object", + "description": "A provider job: the provider's job id and its status checks." + }, + "ideal": { + "description": "A provider job: the circuit's exact distribution set beside the measured counts.", + "anyOf": [ + { + "type": "object", + "required": [ + "computed", + "total_variation_distance", + "hellinger_fidelity" + ], + "properties": { + "computed": { + "const": true + }, + "method": { + "type": "string" + }, + "total_variation_distance": { + "type": "number" + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_expected": { + "type": "number" + }, + "ideal_outcomes": { + "type": "integer" + }, + "note": { + "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "computed", + "why" + ], + "properties": { + "computed": { + "const": false + }, + "why": { + "type": "string" + } + } + } + ] + }, + "cost": { + "type": "object", + "description": "A provider job: the estimate shown before it was sent, what the provider says it charged, and whether the person confirmed a run that was not free." + }, + "provenance": { + "title": "wai.quantum.provenance/1", + "description": "What a result came from, under the five categories cross-platform provenance surveys use: the circuit, the computer, the compilation, the execution and the software. A host adds it to the results it seals (the job service does, and each item of a set); a result without it reads as it always did. wai-quantum-service/docs/provenance.md maps every field to where it is and whether the receipt seals it.", + "type": "object", + "required": [ + "schema", + "circuit", + "computer", + "compilation", + "execution", + "software" + ], + "properties": { + "schema": { + "const": "wai.quantum.provenance/1" + }, + "circuit": { + "type": "object", + "description": "The program: the BLAKE3 digest of its text as given, its qubits and its gates.", + "required": [ + "program" + ], + "properties": { + "program": { + "type": "string", + "description": "BLAKE3 of the program's text, in hex." + }, + "qubits": { + "type": "integer", + "minimum": 0 + }, + "gates": { + "type": [ + "integer", + "null" + ] + } + } + }, + "computer": { + "type": "object", + "description": "What ran it: a classical simulator, the method and its accuracy class, a device target's hash when the job named one, and the fabric's members when the result names where its state ran.", + "required": [ + "kind", + "method" + ], + "properties": { + "kind": { + "const": "simulator" + }, + "method": { + "type": "string" + }, + "accuracy": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": "string", + "description": "The device target's hash; its layout, routes and noise are in the result's own target." + }, + "fabric": { + "type": "object", + "description": "The kernel and the member that ran the state, or each partition's, as the result's fabric names them.", + "properties": { + "kernel": { + "type": "string" + }, + "members": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "compilation": { + "type": "object", + "description": "Whether the job asked to be compiled; if it did, each pass in order with its check's verdict, the certificate's digest, the gate set compiled to (its basis), the level, the ε budget and the distance the result carries, and that no pass draws a random number.", + "required": [ + "asked" + ], + "properties": { + "asked": { + "type": "boolean" + }, + "passes": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "pass": { + "type": "string" + }, + "verdict": { + "type": [ + "string", + "null" + ] + } + } + } + }, + "certificate": { + "type": [ + "string", + "null" + ] + }, + "basis": { + "type": [ + "string", + "null" + ], + "description": "The gate set compiled to: clifford_t or standard." + }, + "level": { + "type": [ + "integer", + "null" + ] + }, + "epsilon": { + "type": [ + "number", + "null" + ] + }, + "distance": { + "type": [ + "number", + "null" + ] + }, + "seeded": { + "const": false + }, + "device": { + "type": "string", + "description": "A job on a device target, compiled exactly to its gates: where its layout and routes are." + }, + "status": { + "const": "not-applicable" + }, + "why": { + "type": "string" + } + } + }, + "execution": { + "type": "object", + "description": "The shots, the seed and the plan the job ran under; its identifier and times are the host's, outside the result.", + "required": [ + "plan" + ], + "properties": { + "shots": { + "type": [ + "integer", + "null" + ] + }, + "seed": { + "type": [ + "integer", + "null" + ] + }, + "plan": { + "type": "object", + "properties": { + "method": { + "type": "string" + }, + "why": { + "type": "string" + }, + "memory_bytes": { + "type": "integer", + "minimum": 0 + }, + "work": { + "type": "integer", + "minimum": 0 + } + } + } + } + }, + "software": { + "type": "object", + "description": "The engine's name and version, and the host's.", + "required": [ + "engine", + "host" + ], + "properties": { + "engine": { + "type": "string" + }, + "host": { + "type": "string" + } + } + } + } + }, + "mitigation": { + "title": "wai.quantum.mitigation/1", + "description": "A job's mitigation (its request's mitigate, engine::mitigate), in its result: the method and the options it ran with, its bias and variance assumptions, each observable raw and mitigated with a standard error each and the ideal value (or, for readout, the counts inverted as a quasi-distribution), the method's own details and what it spent. docs/qec.md describes each method.", + "type": "object", + "required": [ + "method", + "options", + "assumptions" + ], + "properties": { + "method": { + "enum": [ + "zne", + "pea", + "pec", + "cdr", + "vd", + "readout" + ] + }, + "options": { + "type": "object", + "description": "The options it ran with, the defaults filled in.", + "properties": { + "method": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "factors": { + "type": "array", + "items": { + "type": "number" + } + }, + "extrapolation": { + "enum": [ + "richardson", + "linear", + "exponential" + ] + }, + "samples": { + "type": "integer" + }, + "training": { + "type": "integer" + }, + "keep": { + "type": "integer" + }, + "learn_shots": { + "type": "integer" + } + } + }, + "assumptions": { + "type": "object", + "properties": { + "bias": { + "type": "string" + }, + "variance": { + "type": "string" + } + } + }, + "noise": { + "type": "string", + "description": "How the job's noise model is read for the method." + }, + "note": { + "type": "string" + }, + "observables": { + "type": "array", + "items": { + "type": "object", + "description": "One observable: its raw value and the mitigated one, each with its standard error, and the ideal value a simulation knows.", + "properties": { + "observable": { + "type": "string" + }, + "coeff": { + "type": "number" + }, + "raw": { + "type": "number" + }, + "raw_stderr": { + "type": "number" + }, + "mitigated": { + "type": "number" + }, + "stderr": { + "type": "number" + }, + "ideal": { + "type": "number" + } + } + } + }, + "distribution": { + "type": "array", + "description": "readout: each outcome's raw share and its mitigated quasi-probability, with its standard error.", + "items": { + "type": "object", + "properties": { + "bits": { + "type": "string" + }, + "raw": { + "type": "number" + }, + "mitigated": { + "type": "number" + }, + "stderr": { + "type": "number" + } + } + } + }, + "details": { + "type": "object", + "description": "The method's own: the folded scales and the folding check (zne), the learned model and the amplified values (pea), the quasi-probability and the value it converges to (pec), the training fits (cdr), the purity (vd), the flip and its amplification (readout).", + "additionalProperties": true + }, + "cost": { + "type": "object", + "description": "The circuits and shots it spent beyond the job's own.", + "properties": { + "circuits": { + "type": "integer", + "minimum": 0 + }, + "shots": { + "type": "integer", + "minimum": 0 + }, + "note": { + "type": "string" + } + } + } + } + }, + "pulse": { + "type": "object", + "description": "A pulse run (method pulse, engine::pulse): what was read and its distribution, the final populations, each capture's reading, the final density matrix's digest, the schedule's length, the integrator and its step, the device and where each parameter came from, and what the receipt binds (calibration).", + "required": [ + "read", + "outcome_bits", + "populations", + "simulated_qubits", + "density_hash", + "integrator", + "device", + "calibration" + ], + "properties": { + "read": { + "type": "string", + "description": "What the distribution reads: the captures together (into the program's bits when each writes one), or the final state." + }, + "outcome_bits": { + "type": "array", + "items": { + "type": "string" + }, + "description": "What each character of an outcome is, left to right: a program bit (c[0]) or a qubit ($0)." + }, + "distribution": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "number" + }, + "description": "The probability of each outcome, which the counts sample; null when the captures start at different samples." + }, + "populations": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "The final state read on every simulated qubit, the highest qubit first, a level above 0 read as 1." + }, + "simulated_qubits": { + "type": "array", + "items": { + "type": "integer" + } + }, + "captures": { + "type": "array", + "items": { + "type": "object", + "properties": { + "frame": { + "type": "string" + }, + "qubit": { + "type": "integer" + }, + "start": { + "type": "integer" + }, + "start_ns": { + "type": "number" + }, + "bit": { + "type": [ + "string", + "null" + ] + }, + "p1": { + "type": "number" + }, + "p2": { + "type": "number" + } + } + } + }, + "leakage": { + "type": "array", + "items": { + "type": "object", + "properties": { + "qubit": { + "type": "integer" + }, + "p2": { + "type": "number" + } + } + }, + "description": "With three levels: each qubit's final probability of level 2." + }, + "trace": { + "type": "number" + }, + "density_hash": { + "type": "string", + "description": "The BLAKE3 of the final density matrix's bits: the same on every platform." + }, + "duration": { + "type": "integer" + }, + "duration_ns": { + "type": "number" + }, + "integrator": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "dt_ns": { + "type": "number" + }, + "substeps": { + "type": "integer" + }, + "step_ns": { + "type": "number" + }, + "steps": { + "type": "integer" + }, + "norm_max": { + "type": "number" + }, + "frame": { + "type": "string" + } + } + }, + "device": { + "type": "object", + "properties": { + "levels": { + "type": "integer" + }, + "dt_ns": { + "type": "number" + }, + "qubits": { + "type": "array", + "items": { + "type": "object", + "properties": { + "qubit": { + "type": "integer" + }, + "frequency_hz": { + "type": "number" + }, + "rabi_hz": { + "type": "number" + }, + "anharmonicity_hz": { + "type": "number" + }, + "t1_ns": { + "type": "number" + }, + "t2_ns": { + "type": "number" + }, + "from": { + "type": "object", + "additionalProperties": { + "enum": [ + "pulse", + "target", + "default", + "none" + ] + } + } + } + } + }, + "couplings": { + "type": "array" + }, + "model": { + "type": "string" + } + } + }, + "calibration": { + "type": "object", + "description": "What the receipt binds: the program's, its calibrations', the schedule's and the device's digests, and the target snapshot.", + "properties": { + "program": { + "type": "string" + }, + "calibrations": { + "type": "string" + }, + "schedule": { + "type": "string" + }, + "device": { + "type": "string" + }, + "target": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "calibration": { + "type": "object" + } + } + } + } + }, + "not_modelled": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, diff --git a/wai/wai-quantum-cli/docs/service-mcp.json b/wai/wai-quantum-cli/docs/service-mcp.json index eb163cebb..6f2bf1f05 100644 --- a/wai/wai-quantum-cli/docs/service-mcp.json +++ b/wai/wai-quantum-cli/docs/service-mcp.json @@ -530,6 +530,78 @@ }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes." }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } + }, "idempotency_key": { "type": "string", "minLength": 1, @@ -1374,6 +1446,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -1492,9 +1636,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -4210,6 +4355,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -5220,6 +6343,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -5336,9 +6531,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -8054,6 +9250,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -8699,6 +10873,677 @@ } } }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, "verdict": { "title": "wai.quantum.verdict/1", "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", @@ -11632,6 +14477,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -11750,9 +14667,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -14468,6 +17386,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -15478,6 +19374,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -15594,9 +19562,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -18312,6 +22281,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -18957,6 +23904,677 @@ } } }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, "verdict": { "title": "wai.quantum.verdict/1", "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", @@ -21071,6 +26689,78 @@ "description": "The program's bytes as base64: jeff." } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -21284,6 +26974,677 @@ } } }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, "verdict": { "title": "wai.quantum.verdict/1", "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", @@ -22910,6 +29271,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -23028,9 +29461,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -25746,6 +32180,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -26756,6 +34168,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -26872,9 +34356,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -29590,6 +37075,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -30235,6 +38698,677 @@ } } }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, "verdict": { "title": "wai.quantum.verdict/1", "description": "How far the engine checked an answer about a program, as one level of an ordered ladder (wai-quantum://docs/verdicts): refused, parsed, executed, evidence, proof. A level says how far the engine checked, not that the answer is good: holds says whether the intents held (true, false, or null when none was decided). A job's result carries one under verdict when the job gives an intent or asks for one, and the receipt seals it; both MCP servers state one beside every answer about a program.", @@ -31861,6 +40995,10 @@ "type": "object", "description": "For a provider's result, what it says of itself." }, + "planner": { + "type": "object", + "description": "For a job under a contract, what its reasoning says: the route chosen, the class wanted and given, whether the choice depends on the host, what was kept, and the shadow." + }, "key": { "type": [ "string", @@ -44644,12 +53782,77 @@ } } }, - "params": { - "type": "object", - "additionalProperties": { - "type": "number" - }, - "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes." + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } }, "seed": { "type": "integer", @@ -45089,6 +54292,13 @@ } } }, + "params": { + "type": "object", + "additionalProperties": { + "type": "number" + }, + "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes." + }, "idempotency_key": { "type": "string", "minLength": 1, @@ -45933,6 +55143,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -46051,9 +55333,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -48769,6 +58052,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -49779,6 +60040,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } }, @@ -49895,9 +60228,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -52613,6 +62947,984 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": [ + "at", + "joules", + "max_joules", + "elapsed_ms", + "read" + ], + "properties": { + "at": { + "const": "max_joules" + }, + "joules": { + "type": "number", + "description": "What the reading had come to, at or past the ceiling." + }, + "max_joules": { + "type": "number" + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "read": { + "type": "string", + "description": "What read the run, and what that covers." + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "type": "object", + "description": "What the method promises of the numbers it gave.", + "required": [ + "class" + ], + "properties": { + "class": { + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "none" + ], + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." + }, + "approximate": { + "const": true, + "description": "A simulated result whose provider states its simulator is approximate." + }, + "note": { + "type": "string" + }, + "global_phase": { + "type": "object", + "description": "The bit-exact method: method statevector's state of the program that ran is e^(i radians) times the amplitudes given, since this method's lowering drops the phase of rz, rx, ry, rxx, ryy, rzz and u. Absent when that is 1. The language's own state can differ from both: its U is e^(i theta / 2) times the matrix both methods take as u, the reader drops an uncontrolled gphase (Q206), and a compiled job's program is the compile's, right up to a global phase.", + "required": [ + "turns_over_2_33", + "radians", + "note" + ], + "properties": { + "turns_over_2_33": { + "type": "integer", + "minimum": 0, + "description": "The phase exactly, in 2^33rds of a turn." + }, + "radians": { + "type": "number", + "description": "The same in radians, in (-pi, pi]." + }, + "note": { + "type": "string" + } + } + }, + "below_table": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering that are not zero and ran as no phase, within the reader's tolerance (1e-14 of a turn) of a whole turn. `angles` counts those gates: one angle written may be several, and another count in another form of the same program.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "moved_angles": { + "type": "object", + "description": "The bit-exact method: phase gates of its lowering within the reader's tolerance (1e-14 of a turn) of a dyadic angle, by more than a double's rounding of it, that ran as it. `angles` counts those gates.", + "required": [ + "angles", + "largest_radians", + "note" + ], + "properties": { + "angles": { + "type": "integer", + "minimum": 1 + }, + "largest_radians": { + "type": "number" + }, + "note": { + "type": "string" + } + } + }, + "fusion": { + "type": "integer" + }, + "device": { + "type": "string" + }, + "threshold": { + "type": "number" + }, + "max_weight": { + "type": [ + "integer", + "null" + ] + }, + "max_bond": { + "type": "integer" + }, + "max_bond_used": { + "type": "integer" + }, + "discarded_weight": { + "type": "number" + }, + "fidelity_estimate": { + "type": "number" + }, + "truncations": { + "type": "integer" + }, + "shots": { + "type": "integer" + }, + "trajectories": { + "type": "integer" + }, + "histories": { + "type": "integer" + }, + "gate_applications": { + "type": "integer" + }, + "max_cut": { + "type": "integer" + }, + "order_work": { + "type": "number" + }, + "batch": { + "type": "integer" + }, + "bound": { + "type": "number", + "description": "The bound this result is held to, by method: a pulse run (class bounded): every probability within this of the exact solution of the model's master equation, the truncation bound and the rounding estimate together; stabilizer_rank's sampled mode (class estimate): the bound on the distance of the estimated state from the state, holding with the probability confidence states.", + "minimum": 0 + }, + "truncation_bound": { + "type": "number", + "description": "A pulse run: the proved bound, in the trace norm, on what the integrator's series leaves out." + }, + "rounding_estimate": { + "type": "number", + "description": "A pulse run: an estimate of floating-point rounding beside the bound, not a proof." + }, + "tolerance": { + "type": "number" + }, + "norm": { + "type": "string" + }, + "t_count": { + "type": "integer", + "minimum": 0, + "description": "stabilizer_rank: the T and T† gates the program lowers to." + }, + "terms": { + "type": "integer", + "minimum": 1, + "description": "stabilizer_rank: the stabilizer branches summed (2^t exactly), or drawn." + }, + "confidence": { + "type": "number", + "description": "The probability a stated bound holds." + } + } + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } }, @@ -52892,6 +64204,677 @@ } } } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } } } }, @@ -53809,6 +65792,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } } } diff --git a/wai/wai-quantum-cli/schemas/local-tools.v1.json b/wai/wai-quantum-cli/schemas/local-tools.v1.json index 7ea23dbf6..47237c1c8 100644 --- a/wai/wai-quantum-cli/schemas/local-tools.v1.json +++ b/wai/wai-quantum-cli/schemas/local-tools.v1.json @@ -49,6 +49,28 @@ "null" ], "description": "That key as a did:key." + }, + "planner": { + "type": "object", + "description": "For a job under a contract, what its reasoning says: the route chosen, the class wanted and given, whether the choice depends on the host, what was kept, and the shadow." + }, + "recheck": { + "type": "object", + "description": "With recheck: whether the routes priced again and the shadow run again are what the job sealed.", + "properties": { + "holds": { + "type": "boolean" + }, + "engine": { + "type": "object" + }, + "priced": { + "type": "object" + }, + "shadow": { + "type": "object" + } + } } } }, @@ -471,6 +493,55 @@ "confirm": { "type": "string", "description": "What the person reads before confirming a run that is not free." + }, + "planner": { + "$ref": "https://git.transaction.science/Transaction-Science/open-standards/raw/branch/main/wai/wai-quantum/schemas/job-result.v1.json#/$defs/planner" + } + } + }, + "routed": { + "type": "object", + "description": "Every route a job could take under its contract, each with its price or why it was rejected, and the route chosen: nothing submitted, nothing spent.", + "required": [ + "dry_run", + "planner" + ], + "properties": { + "dry_run": { + "const": true + }, + "planner": { + "$ref": "https://git.transaction.science/Transaction-Science/open-standards/raw/branch/main/wai/wai-quantum/schemas/job-result.v1.json#/$defs/planner" + }, + "plan": { + "$ref": "https://git.transaction.science/Transaction-Science/open-standards/raw/branch/main/wai/wai-quantum/schemas/plan.v1.json" + }, + "provider_plan": { + "$ref": "#/$defs/provider_estimate" + }, + "confirm": { + "type": "object", + "description": "Where the route chosen is a provider's and not free: what a person confirms it by. token is a digest of the route, its estimate's money and the program and shots it would send; a run is sent only when given that token made again at send time.", + "required": [ + "token", + "route", + "money", + "says" + ], + "properties": { + "token": { + "type": "string" + }, + "route": { + "type": "string" + }, + "money": { + "type": "object" + }, + "says": { + "type": "string" + } + } } } } diff --git a/wai/wai-quantum-cli/skills/wai-quantum/reference/tools.md b/wai/wai-quantum-cli/skills/wai-quantum/reference/tools.md index 02c4a3468..8bd99be2d 100644 --- a/wai/wai-quantum-cli/skills/wai-quantum/reference/tools.md +++ b/wai/wai-quantum-cli/skills/wai-quantum/reference/tools.md @@ -55,6 +55,8 @@ Generated by `wai-quantum docs skill` from the servers' own lists; `wai-quantum - `providers_list`: List the person's quantum providers - `provider_estimate`: Plan a run on a provider, and its cost - `run_on_provider`: Run on a provider (can spend the person's money) +- `plan_routes`: Weigh a contract against every route +- `run_routed`: Run a job on the route its contract chooses (can spend the person's money) - `get_provider_job`: Ask after a job on a provider - `cancel_provider_job`: Cancel a job on a provider - `list_provider_jobs`: List the jobs on the person's providers diff --git a/wai/wai-quantum-cli/src/estimates.rs b/wai/wai-quantum-cli/src/estimates.rs new file mode 100644 index 000000000..2d5264330 --- /dev/null +++ b/wai/wai-quantum-cli/src/estimates.rs @@ -0,0 +1,1058 @@ +//! What this command line says of a run's energy before it runs, and the live +//! reading that holds a contract's `max_joules` (`--max-joules`) while it runs. +//! +//! No figure before a run can promise a ceiling: a job's work leaves out what +//! drives its time, and the same job read twice differs. So a run under a ceiling +//! runs in a process of its own ([`run_watched`]), which this one reads about every +//! ten milliseconds as the host schedules it (on macOS that process's CPU energy; +//! on Linux the processor packages', where this user may read them) and kills at +//! the ceiling, so the work stops there. Its whole figure is read when it ends, +//! killed or not, and sealed; a stopped run's receipt says so, and the longest time +//! between two reads. Where nothing can read the run, or stop it, the route is +//! refused under a ceiling and says why: a method on a device no counter here +//! reads, a host with no counter that reads, or a server, which runs jobs in its +//! own process. +//! +//! What was read is kept, in `$WAI_QUANTUM_TIMINGS` (`off` keeps none), or +//! `$XDG_CONFIG_HOME/wai/quantum-timings.json`, or +//! `~/.config/wai/quantum-timings.json`, the last 32 runs of each method on each +//! machine, reader and build: the basis of an estimate beside each route, labelled +//! one, which can refuse a job clearly past a ceiling and promises nothing. Nothing +//! is sent anywhere. A run is read only where something needs the reading: a +//! ceiling on it, or a method with too few runs read to estimate from. Only `run` +//! reads: a server, a test or an embedded runner adds nothing to what is kept. A +//! wasm build keeps no file and reads no counter. +//! +//! A run without a ceiling runs in this process, and a reading there is never +//! sealed: what a process reads of itself leaves out memory, the host's idle draw +//! and any device it drives, and the packages count every process on them. + +use serde_json::{Map, Value, json}; +use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; +use std::sync::OnceLock; +use std::sync::atomic::{AtomicU64, Ordering}; +use std::time::{Duration, Instant}; +use wai_quantum::engine::catalog::Plan; +use wai_quantum::engine::energy::{self, Held, TIMINGS, Timing}; +use wai_quantum::engine::planner; + +/// The file's form. +pub const SCHEMA: &str = "wai.quantum.timings/1"; +/// Whose readings an estimate rests on, in its words. +const HOST: &str = "this command line"; +/// How long a process's own counter takes to catch up with its threads: they +/// leave their cores, and their energy is counted. +const SETTLE: Duration = Duration::from_millis(5); +/// A run is read over at least this many of a package counter's updates: a window +/// shorter than a few reads a step or nothing. +const LEAST_UPDATES: u64 = 4; +/// The runs read before an estimate rests on them. +const ESTIMATE_RUNS: usize = 3; + +/// Where the timings are kept, by `var`: a value that is empty is one not set, as +/// XDG says, and an `XDG_CONFIG_HOME` that is not absolute is ignored, as XDG says. +fn path_from(var: impl Fn(&str) -> Option) -> Option { + let set = |k: &str| var(k).filter(|v| !v.is_empty()); + if let Some(p) = set("WAI_QUANTUM_TIMINGS") { + return (p != "off").then(|| PathBuf::from(p)); + } + let base = set("XDG_CONFIG_HOME").map(PathBuf::from).filter(|p| p.is_absolute()).or_else(|| set("HOME").map(|h| Path::new(&h).join(".config")))?; + Some(base.join("wai").join("quantum-timings.json")) +} + +/// Where the timings are kept: nowhere in a wasm build, or in this binary's own +/// tests, which name their file. +pub fn path() -> Option { + if cfg!(any(test, target_family = "wasm")) { + return None; + } + path_from(|k| std::env::var_os(k)) +} + +/// What keeps readings from one machine, reader or build out of another's +/// estimate: a home shared between two machines, a debug and a release build, an +/// older version, or a build with other features on one. +fn identity() -> String { + let reader = if cfg!(target_os = "macos") { + "process" + } else if cfg!(target_os = "linux") { + "packages" + } else { + "none" + }; + let profile = if cfg!(debug_assertions) { "debug" } else { "release" }; + let features: Vec<&str> = [("metal", cfg!(feature = "metal")), ("cuda", cfg!(feature = "cuda")), ("hip", cfg!(feature = "hip")), ("opencl", cfg!(feature = "opencl"))].into_iter().filter_map(|(f, on)| on.then_some(f)).collect(); + format!("{} {}-{} {reader} {} {profile} {}", energy::machine(), std::env::consts::OS, std::env::consts::ARCH, env!("CARGO_PKG_VERSION"), features.join("+")) +} + +/// What a live reading here covers, for a route's `watch` and a stopped run's `read`. +fn scope() -> String { + let every = energy::WATCH_MS; + if cfg!(target_os = "macos") { + format!("the CPU energy of the run's own process, read about every {every} ms as the host schedules it; not memory or the host's idle draw") + } else { + format!("the processor packages' energy, read about every {every} ms as the host schedules it: every process on them, so a busy host stops a run sooner; not memory") + } +} + +/// Whether `method` runs on a device no counter here reads. +fn is_device(method: &str) -> bool { + wai_quantum::engine::planner::is_gpu(method) +} + +/// A build with fabric members other than the CPU: `auto` can place a job there. +const ACCELERATORS: bool = cfg!(any(feature = "cuda", feature = "hip", feature = "opencl")); + +/// Whether `request` can be placed on a member other than the CPU. +fn placed(request: &Value) -> bool { + match request.get("fabric") { + None | Some(Value::Null) => ACCELERATORS, + Some(Value::String(s)) if s == "auto" => ACCELERATORS, + Some(Value::String(s)) if s == "cpu" => false, + Some(_) => true, + } +} + +/// This command line's readings of each method, on this machine. +#[derive(Debug, Default)] +pub struct Book { + runs: BTreeMap>, + unmetered: Option, + placed: bool, + /// Why this surface cannot stop a run, where it cannot. + embedded: Option<&'static str>, +} + +/// What a run of a job here is: `run`, this process's one run, which a reading can +/// stop, or a run inside a process with other work in it, which none can. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Surface { + Run, + Embedded, +} + +fn timing_of(v: &Value) -> Option { + Some(Timing { + work: v["work"].as_u64()?, + elapsed_ms: v["elapsed_ms"].as_u64()?, + watts: v["watts"].as_f64().filter(|w| w.is_finite() && *w > 0.0), + window_us: v["window_us"].as_u64().filter(|u| *u > 0), + partial: v["partial"] == true, + }) +} + +fn value_of(t: &Timing) -> Value { + json!({ "work": t.work, "elapsed_ms": t.elapsed_ms, "window_us": t.window_us, "watts": t.watts, "partial": t.partial }) +} + +/// The file as it stands: nothing yet, or its value, or why it is no store of +/// timings, which is never written over. +enum Stored { + Nothing, + Store(Value), + Other(String), +} + +fn stored(p: &Path) -> Result { + let text = match std::fs::read_to_string(p) { + Ok(t) => t, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(Stored::Nothing), + Err(e) if e.kind() == std::io::ErrorKind::InvalidData => return Ok(Stored::Other(format!("it is not text: {e}"))), + Err(e) => return Err(format!("{}: {e}", p.display())), + }; + Ok(match serde_json::from_str::(&text) { + Ok(v) if v["schema"] == SCHEMA => Stored::Store(v), + Ok(v) => Stored::Other(format!("its schema is {}, not {SCHEMA}", v["schema"])), + Err(e) => Stored::Other(format!("it does not read: {e}")), + }) +} + +impl Book { + /// The readings at [`path`]; none where the file is missing or not of its form. + pub fn load() -> Book { + Book::at(path().as_deref()) + } + + /// The readings at `path`, on this machine. + pub fn at(path: Option<&Path>) -> Book { + let v = path.and_then(|p| stored(p).ok()).and_then(|s| if let Stored::Store(v) = s { Some(v) } else { None }); + let mut runs = BTreeMap::new(); + for (method, list) in v.as_ref().and_then(|v| v["machines"][identity()].as_object()).into_iter().flatten() { + let mut kept: Vec = list.as_array().into_iter().flatten().filter_map(timing_of).collect(); + let over = kept.len().saturating_sub(TIMINGS); + kept.drain(..over); + runs.insert(method.clone(), kept); + } + Book { runs, unmetered: unmetered(false), placed: false, embedded: None } + } + + /// The readings for a contract's `request` on `surface`. Under a ceiling, a + /// counter that does not step is found now, and the refusal says so. + pub fn for_job(request: &Value, surface: Surface) -> Book { + let mut b = Book::load(); + b.placed = placed(request); + if surface == Surface::Embedded { + b.embedded = Some("this server runs jobs in a process with other work in it, so nothing can stop one: run it with `wai-quantum run`"); + } + if ceiling(request).is_some() { + b.unmetered = unmetered(true); + } + b + } + + /// What this host says of `plan`'s energy: an estimate from what is kept, and + /// what would read the run ([`Held`]). + pub fn held(&self, plan: &Plan) -> Held { + let device = if is_device(&plan.method) { + Some("the GPU") + } else if self.placed && matches!(plan.method.as_str(), "statevector" | "pauli") { + Some("an accelerator") + } else { + None + }; + let watch = match (device, self.embedded, &self.unmetered) { + (Some(d), ..) => Err(format!("it runs on {d}, which no counter here reads")), + (None, Some(why), _) => Err(why.to_string()), + (None, None, Some(why)) => Err(format!("this host reads no energy: {why}")), + (None, None, None) => Ok(scope()), + }; + // What was read of a run on a device leaves out what did the work. + let mine: Vec = self.runs.get(&plan.method).map_or(Vec::new(), |l| l.iter().filter(|t| !t.partial).copied().collect()); + let e = energy::estimate(plan, &mine, HOST, self.unmetered.as_deref(), 0).energy; + let estimate = match e["joules_micro_estimate"].as_u64() { + Some(u) => Ok((u as f64 / 1e6, format!("an estimate, which promises nothing: the median power of the last {} {} runs this command line read, over the estimated time", mine.iter().filter(|t| t.watts.is_some()).count(), plan.method))), + None => Err(e["unestimated"].as_str().unwrap_or("this command line has no estimate").to_string()), + }; + Held { estimate, watch } + } + + /// Whether an estimate of `method` still wants runs read. + fn wants(&self, method: &str) -> bool { + self.runs.get(method).map_or(0, |l| l.iter().filter(|t| t.watts.is_some()).count()) < ESTIMATE_RUNS + } +} + +/// The ceiling `request`'s contract gives, in joules, where it gives one. +pub fn ceiling(request: &Value) -> Option { + request.pointer("/contract/max_joules").and_then(Value::as_f64) +} + +/// Whether a run of `request` wants reading: a ceiling on it, or a method it +/// would run with too few runs read to estimate from. A counter costs a run time, and +/// on Linux its first read costs a third of a second. +pub fn wanted(book: &Book, request: &Value, job_bytes: u64) -> bool { + wanted_keeping(book, request, job_bytes, path().is_some()) +} + +/// [`wanted`], where `keeping` says whether what is read is kept: a reading kept +/// nowhere is not worth a counter's probe. +fn wanted_keeping(book: &Book, request: &Value, job_bytes: u64, keeping: bool) -> bool { + !cfg!(target_family = "wasm") && (ceiling(request).is_some() || (keeping && wai_quantum::engine::catalog::plan(request, job_bytes).is_ok_and(|p| book.wants(&p.method)))) +} + +/// Why this command line reads no energy counter here, where it reads none. +/// `live`: whether to find out if a package counter steps, once in a process. +pub fn unmetered(live: bool) -> Option { + if cfg!(target_family = "wasm") { + return Some("a wasm build reads no energy counter".to_string()); + } + if cfg!(target_os = "macos") { + return (!own_reads()).then(|| "this process's CPU energy counter does not read here".to_string()); + } + if cfg!(target_os = "linux") { + return match energy::access_in(Path::new("/sys/class/powercap")) { + energy::Access::Readable if live => packages().as_ref().err().cloned(), + energy::Access::Readable => None, + a => Some(a.why().to_string()), + }; + } + Some("this command line reads no energy counter on this system".to_string()) +} + +/// The package counters, opened and found live once in a process: finding out +/// takes a third of a second. +fn packages() -> &'static Result { + static PACKAGES: OnceLock> = OnceLock::new(); + PACKAGES.get_or_init(energy::Packages::open) +} + +/// What the counter read around a run: the time it read over, and the energy +/// over that time where it read on both sides. +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Read { + pub window_us: u64, + pub joules: Option, +} + +impl Read { + fn over(window: Duration, joules: Option) -> Read { + Read { window_us: u64::try_from(window.as_micros()).unwrap_or(u64::MAX).max(1), joules: joules.filter(|j| j.is_finite() && *j > 0.0) } + } + + /// The power over the window. + pub fn watts(&self) -> Option { + self.joules.map(|j| j / (self.window_us as f64 / 1e6)) + } +} + +/// A process's own counter, read after it settles: the wait is in the energy and +/// not in the window, since a process waiting takes no energy to speak of, and a +/// power over a window with an idle wait in it is low by the wait. +fn settled(began: Instant, wait: Duration, joules: impl FnOnce() -> Option) -> Read { + let window = began.elapsed(); + std::thread::sleep(wait); + Read::over(window, joules()) +} + +/// The packages, read over at least [`LEAST_UPDATES`] of the counter's updates: +/// the wait is in both the energy and the window, which then read the same span, +/// and the energy is taken up by the step it can be short by. None past the time +/// a counter can wrap twice ([`energy::wrap_seconds`]), or where it did not step. +fn over_updates(began: Instant, p: &energy::Packages, before: &energy::PackageSnapshot) -> Read { + let least = Duration::from_nanos(p.probe.update_ns.saturating_mul(LEAST_UPDATES)); + if let Some(left) = least.checked_sub(began.elapsed()) { + std::thread::sleep(left); + } + let after = p.read(); + let window = began.elapsed(); + let trusted = p.wrap_seconds().is_some_and(|s| window.as_secs_f64() < s); + let joules = after.and_then(|a| p.between(before, &a, 0)).filter(|r| trusted && r.energy_uj > 0).map(|r| (r.energy_uj + r.step_uj) as f64 / 1e6); + Read::over(window, joules) +} + +/// What is read before a run. +enum Before { + Own(energy::Reading), + Packages(&'static energy::Packages, energy::PackageSnapshot), + Nothing, +} + +/// A run being read: its start, and the counter as it stood. +pub struct Around { + began: Instant, + before: Before, +} + +impl Around { + /// The counter read now, before a run, where one reads and `wanted`. + pub fn begin(wanted: bool) -> Around { + let before = if !wanted { + Before::Nothing + } else if cfg!(target_os = "macos") { + energy::own().map_or(Before::Nothing, Before::Own) + } else if cfg!(target_os = "linux") { + packages().as_ref().ok().map_or(Before::Nothing, Around::on) + } else { + Before::Nothing + }; + Around { began: Instant::now(), before } + } + + fn on(p: &'static energy::Packages) -> Before { + p.read().map_or(Before::Nothing, |s| Before::Packages(p, s)) + } + + /// What the counter read over the run. + pub fn end(self) -> Read { + match &self.before { + Before::Own(b) => settled(self.began, SETTLE, || energy::own().map(|a| a.joules() - b.joules())), + Before::Packages(p, b) => over_updates(self.began, p, b), + Before::Nothing => Read::over(self.began.elapsed(), None), + } + } +} + +/// `run` read around, where `wanted`: its answer, and what the counter read. +pub fn read_run(wanted: bool, run: impl FnOnce() -> T) -> (T, Read) { + let around = Around::begin(wanted); + let out = run(); + (out, around.end()) +} + +/// The argument a run under a ceiling is started with in its own process. +pub const WORKER: &str = "__run-under-a-ceiling"; + +/// How a run under a ceiling in its own process ended. +pub enum Ended { + /// It finished: what it wrote, its exit, its energy as a figure to seal, and + /// what was read of it. + Finished { out: Vec, err: Vec, status: std::process::ExitStatus, figure: Value, read: Read }, + /// It reached the ceiling and was killed: what stopped it, and its whole figure. + Stopped { stopped: planner::Stopped, figure: Value }, +} + +/// What reads a run in its own process: on macOS that process's CPU energy, on +/// Linux the processor packages' since it began, added up read by read. +enum Meter<'a> { + Process, + Packages(energy::Accumulated<'a>), +} + +/// Whether this process's own counter reads here: a read of nothing is taken again +/// after a short spin, since an idle process can read nothing on a live counter. +pub fn own_reads() -> bool { + reads_after(|| energy::own().is_some(), || { + let until = Instant::now() + Duration::from_millis(20); + while Instant::now() < until { + std::hint::spin_loop(); + } + }) +} + +/// `read`, and where it gives nothing, `spend` and `read` again. +fn reads_after(mut read: impl FnMut() -> bool, spend: impl FnOnce()) -> bool { + read() || { + spend(); + read() + } +} + +/// `input` run by `exe WORKER` in its own process under `ceiling` joules: read every +/// [`energy::WATCH_MS`] as the host schedules this one, and killed at once at the +/// ceiling, so the work stops there; its whole figure is read after it ends, killed +/// or not, and sealed. A counter silent, or frozen, for a second stops it too +/// ([`energy::Watcher`]). Its standard input stays open while this process lives, +/// so that it ends with this one however this one ends. +pub fn run_watched(exe: &Path, input: &Value, ceiling: f64) -> Result { + use std::io::{Read as _, Write as _}; + use std::process::{Command, Stdio}; + raise_watch(); + default_sigchld(); + let mut meter = if cfg!(target_os = "macos") { + if !own_reads() { + return Err("this process's CPU energy counter does not read here".into()); + } + Meter::Process + } else { + let p = packages().as_ref().map_err(String::clone)?; + Meter::Packages(energy::Accumulated::new(p, p.read().ok_or("the processor packages' counter did not read")?)) + }; + let began = Instant::now(); + let mut child = Command::new(exe).arg(WORKER).env("WAI_QUANTUM_PARENT", std::process::id().to_string()).stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn().map_err(|e| format!("the run's process did not start: {e}"))?; + let pid = child.id(); + let fail = |child: &mut std::process::Child, why: String| { + let _ = child.kill(); + let _ = child.wait(); + why + }; + // The job on one line; the pipe then stays open until this process is done with it. + // A process that ended before it read its job says why by how it ended, which + // the watch below reads: a write it did not take is no error of its own. + let mut held = child.stdin.take(); + if let Some(stdin) = held.as_mut() { + let _ = stdin.write_all(format!("{input}\n").as_bytes()).and_then(|_| stdin.flush()); + } + let drain = |r: Option>| { + std::thread::Builder::new().spawn(move || { + let mut out = Vec::new(); + if let Some(mut r) = r { + let _ = r.read_to_end(&mut out); + } + out + }) + }; + let out = match drain(child.stdout.take().map(|o| Box::new(o) as Box)) { + Ok(t) => t, + Err(e) => return Err(fail(&mut child, format!("no thread could read the run: {e}"))), + }; + let err = match drain(child.stderr.take().map(|e| Box::new(e) as Box)) { + Ok(t) => t, + Err(e) => return Err(fail(&mut child, format!("no thread could read the run: {e}"))), + }; + // The first gap counts from the run's start, not from the watcher's. + let mut watcher = energy::Watcher::new_at(ceiling, began); + let ended = loop { + // Ended: read whole, then reaped (on macOS a process is readable whole + // between its exit and its reaping). + let exited = match &meter { + Meter::Process => energy::read(pid).map(Some), + Meter::Packages(_) => child.try_wait().map_err(|e| format!("the run's process could not be watched: {e}"))?.map(|_| None), + }; + if let Some(reading) = exited { + let status = child.wait().map_err(|e| format!("the run's process could not be reaped: {e}"))?; + // An exited read that stood where the live reads stood while the run spent + // CPU time is a frozen counter's, and no reading. + let frozen = reading.is_some_and(|r| watcher.stood_still(r.joules(), Some(r.cpu_ns))); + let (figure, joules) = if frozen { + (json!({ "unmetered": "the run's counter stood still while it spent CPU time: it is frozen, and no reading" }), None) + } else { + whole(&mut meter, reading) + }; + break Ended::Finished { out: Vec::new(), err: Vec::new(), status, figure, read: Read::over(began.elapsed(), joules) }; + } + let (now, cpu) = match &mut meter { + Meter::Process => energy::running(pid).map_or((None, None), |r| (Some(r.joules()), Some(r.cpu_ns))), + Meter::Packages(added) => (added.read(), None), + }; + match watcher.take_with(now, cpu) { + Some(energy::Watched::Reached(joules)) => { + let _ = child.kill(); + let elapsed_ms = u64::try_from(began.elapsed().as_millis()).unwrap_or(u64::MAX); + let reading = match &meter { + Meter::Process => (0..2000).find_map(|_| energy::read(pid).or_else(|| { + std::thread::sleep(Duration::from_millis(1)); + None + })), + Meter::Packages(_) => None, + }; + let _ = child.wait(); + let figure = no_less_than(whole(&mut meter, reading).0, joules); + break Ended::Stopped { stopped: planner::Stopped { joules, elapsed_ms, read: watcher.said(&scope()) }, figure }; + } + Some(energy::Watched::Lost) => { + let _ = child.kill(); + let _ = child.wait(); + return Err("the counter holding this run's energy ceiling stopped reading, or stood still while the run worked, so the run was stopped: nothing is sealed".into()); + } + None => wait_exit_or(pid, Duration::from_millis(energy::WATCH_MS)), + } + }; + drop(held); + let (o, e) = (out.join().unwrap_or_default(), err.join().unwrap_or_default()); + Ok(match ended { + Ended::Finished { status, figure, read, .. } => Ended::Finished { out: o, err: e, status, figure, read }, + stopped => stopped, + }) +} + +/// A stopped run's whole figure, unless it is below the reading that stopped it, +/// which it cannot honestly be: then no reading. +fn no_less_than(figure: Value, joules: f64) -> Value { + if figure["joules_micro"].as_u64().is_some_and(|u| (u as f64) < joules * 1e6 - 1.0) { + return json!({ "unmetered": "the run's whole reading came to less than the reading that stopped it, so it is no reading" }); + } + figure +} + +/// Until `pid` exits or `timeout` passes: on Linux the run's exit wakes the watch +/// (a pidfd), so its whole figure is read as it ends; elsewhere a sleep. +fn wait_exit_or(pid: u32, timeout: Duration) { + #[cfg(target_os = "linux")] + { + unsafe extern "C" { + fn syscall(number: i64, ...) -> i64; + fn poll(fds: *mut [i32; 2], nfds: u64, timeout: i32) -> i32; + fn close(fd: i32) -> i32; + } + /// `SYS_pidfd_open`, the same number on x86_64 and aarch64. + const SYS_PIDFD_OPEN: i64 = 434; + /// `POLLIN`, in the low half of `struct pollfd`'s second word. + const POLLIN: i32 = 1; + // SAFETY: pidfd_open takes a pid and flags, and returns a descriptor or -1. + let fd = unsafe { syscall(SYS_PIDFD_OPEN, pid as i64, 0i64) } as i32; + if fd >= 0 { + let mut p = [fd, POLLIN]; + // SAFETY: one pollfd ({fd, events, revents}, two 32-bit words here), for the call. + let _ = unsafe { poll(&mut p, 1, i32::try_from(timeout.as_millis()).unwrap_or(i32::MAX)) }; + // SAFETY: the descriptor is this function's. + let _ = unsafe { close(fd) }; + return; + } + } + let _ = pid; + std::thread::sleep(timeout); +} + +/// A run's whole figure, once it has ended: its process's own reading on macOS, the +/// packages' read once more and added up on Linux. With the joules it came to. +fn whole(meter: &mut Meter<'_>, reading: Option) -> (Value, Option) { + match meter { + Meter::Process => (energy::figure(reading.as_ref(), false, "the run's process could not be read when it ended"), reading.map(|r| r.joules())), + Meter::Packages(added) => { + let total = added.read(); + let r = added.reading(0); + (energy::package_figure(total.map(|_| &r), "the processor packages' counter did not read when the run ended"), total) + } + } +} + +/// SIGCHLD as the system has it, whatever this process was started with: a parent +/// that ignores it cannot wait for its child. +fn default_sigchld() { + #[cfg(unix)] + { + unsafe extern "C" { + fn signal(sig: i32, handler: usize) -> usize; + } + /// `SIGCHLD` in ``. + const SIGCHLD: i32 = if cfg!(target_os = "macos") { 20 } else { 17 }; + // SAFETY: SIG_DFL (0) for SIGCHLD changes no memory of this process. + let _ = unsafe { signal(SIGCHLD, 0) }; + } +} + +/// On macOS, this thread's reads at the quality of service of work a person waits +/// on, so that the host does not put them off as it does a background thread's. +fn raise_watch() { + #[cfg(target_os = "macos")] + { + unsafe extern "C" { + fn pthread_set_qos_class_self_np(qos_class: u32, relative_priority: i32) -> i32; + } + /// `QOS_CLASS_USER_INTERACTIVE` in ``. + const USER_INTERACTIVE: u32 = 0x21; + // SAFETY: it sets this thread's own class, and takes no pointer. + let _ = unsafe { pthread_set_qos_class_self_np(USER_INTERACTIVE, 0) }; + } +} + +/// A job body run here, read as `read`: kept beside the runs an estimate rests on, +/// where the counter read it. A run on a device no counter here reads is kept as +/// a reading of part of it. +pub fn keep(body: &Value, read: &Read) { + let Some(p) = path() else { return }; + if let Err(e) = keep_at(&p, body, read) { + eprintln!("note: the run's reading was not kept: {e}"); + } +} + +fn keep_at(p: &Path, body: &Value, read: &Read) -> Result<(), String> { + let (Some(method), Some(work), Some(watts)) = (body["method"].as_str(), body.pointer("/estimate/work").and_then(Value::as_u64), read.watts()) else { return Ok(()) }; + let elapsed_ms = body.pointer("/result/elapsed_ms").and_then(Value::as_u64).unwrap_or(read.window_us / 1000); + let on_member = body.pointer("/result/fabric").is_some_and(|f| !f.is_null() && f["key"] != "cpu"); + add(p, method, &Timing { work, elapsed_ms, watts: Some(watts), window_us: Some(read.window_us), partial: is_device(method) || on_member }) +} + +/// A file a link at `p` names, once: what a link to the store is kept for is the +/// file it names, and a rename over the link would put a file in its place. +fn resolved(p: &Path) -> PathBuf { + match std::fs::read_link(p) { + Ok(to) if to.is_absolute() => to, + Ok(to) => p.parent().map_or(to.clone(), |d| d.join(&to)), + Err(_) => p.to_path_buf(), + } +} + +/// `p` with `suffix` after its whole name. +fn beside(p: &Path, suffix: &str) -> PathBuf { + let mut name = p.file_name().unwrap_or_default().to_os_string(); + name.push(suffix); + p.with_file_name(name) +} + +/// A name no other process or thread writes to. +fn scratch(p: &Path) -> PathBuf { + static NEXT: AtomicU64 = AtomicU64::new(0); + beside(p, &format!(".{}-{:?}-{}.tmp", std::process::id(), std::thread::current().id(), NEXT.fetch_add(1, Ordering::Relaxed))) +} + +/// A file that is no store of timings, moved aside rather than written over, with +/// a note: what it holds is someone's. +fn set_aside(p: &Path, why: &str) -> Result<(), String> { + let aside = (1u32..).map(|n| beside(p, &format!(".unread-{n}"))).find(|a| !a.exists()).ok_or("no name is free")?; + std::fs::rename(p, &aside).map_err(|e| format!("{}: {e}", p.display()))?; + eprintln!("note: {} is no store of timings ({why}): it was kept as {}, and a new one begun", p.display(), aside.display()); + Ok(()) +} + +/// One run of `method` added to the store at `p`: under an advisory lock, so that +/// runs that finish together all keep theirs, what is there is read again, and +/// written back whole through any link. +fn add(p: &Path, method: &str, t: &Timing) -> Result<(), String> { + let at = resolved(p); + if let Some(d) = at.parent().filter(|d| !d.as_os_str().is_empty()) { + std::fs::create_dir_all(d).map_err(|e| format!("{}: {e}", d.display()))?; + } + let lock_path = beside(&at, ".lock"); + let lock = std::fs::OpenOptions::new().create(true).truncate(false).write(true).open(&lock_path).map_err(|e| format!("{}: {e}", lock_path.display()))?; + lock.lock().map_err(|e| format!("{}: {e}", lock_path.display()))?; + let mut v = match stored(&at)? { + Stored::Store(v) => v, + Stored::Nothing => Value::Null, + Stored::Other(why) => { + set_aside(&at, &why)?; + Value::Null + } + }; + if v.is_null() { + v = json!({ + "schema": SCHEMA, + "kept": "only on this machine; nothing is sent anywhere", + "about": "each method's last runs on each machine, as the command line read them around each run: what a ceiling on later runs is bounded by, never a reading of any job", + "machines": {}, + }); + } + let machines = v["machines"].as_object_mut().ok_or("its machines are not an object")?; + let mine = machines.entry(identity()).or_insert_with(|| Value::Object(Map::new())); + let list = mine.as_object_mut().ok_or("a machine's runs are not an object")?.entry(method).or_insert_with(|| json!([])); + let list = list.as_array_mut().ok_or("a method's runs are not an array")?; + list.push(value_of(t)); + let over = list.len().saturating_sub(TIMINGS); + list.drain(..over); + let tmp = scratch(&at); + std::fs::write(&tmp, format!("{}\n", serde_json::to_string_pretty(&v).unwrap_or_default())).map_err(|e| format!("{}: {e}", tmp.display()))?; + std::fs::rename(&tmp, &at).map_err(|e| { + let _ = std::fs::remove_file(&tmp); + format!("{}: {e}", at.display()) + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Arc; + use std::sync::atomic::AtomicBool; + + fn plan(method: &str, work: u64) -> Plan { + Plan { method: method.into(), why: String::new(), memory_bytes: 1, work, qubits: 2, target: None, metered: false } + } + + fn timing(work: u64, window_us: u64, watts: f64) -> Timing { + Timing { work, elapsed_ms: window_us / 1000, watts: Some(watts), window_us: Some(window_us), partial: false } + } + + fn dir(name: &str) -> PathBuf { + let d = std::env::temp_dir().join(format!("wai-quantum-timings-{name}-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&d); + std::fs::create_dir_all(&d).unwrap(); + d + } + + /// A method's last runs are kept, the oldest dropped past 32, and the file + /// reads back as it was written, on this machine alone. + #[test] + fn the_timings_keep_each_method_s_last_runs_and_read_back() { + let d = dir("back"); + let file = d.join("t.json"); + for i in 0..40 { + add(&file, "stabilizer", &timing(1000 + i, 10_000, 2.0)).unwrap(); + } + add(&file, "exact", &timing(5, 7000, 3.0)).unwrap(); + let back = Book::at(Some(&file)); + assert_eq!(back.runs["stabilizer"].len(), TIMINGS); + assert_eq!(back.runs["stabilizer"][0].work, 1008, "the oldest are dropped"); + assert_eq!(back.runs["exact"], [timing(5, 7000, 3.0)]); + // Another machine's readings, in a home they share, are left as they are + // and bound nothing here. + let mut v: Value = serde_json::from_str(&std::fs::read_to_string(&file).unwrap()).unwrap(); + let mine = v["machines"][identity()].clone(); + v["machines"].as_object_mut().unwrap().clear(); + v["machines"]["another-machine linux-x86_64 packages"] = mine.clone(); + std::fs::write(&file, v.to_string()).unwrap(); + assert!(Book::at(Some(&file)).runs.is_empty()); + add(&file, "exact", &timing(5, 7000, 3.0)).unwrap(); + let v: Value = serde_json::from_str(&std::fs::read_to_string(&file).unwrap()).unwrap(); + assert_eq!(v["machines"]["another-machine linux-x86_64 packages"], mine); + let _ = std::fs::remove_dir_all(&d); + } + + /// Three runs read give an estimate, labelled one, which promises nothing, and + /// a run's reading is what a route is held by, whatever the estimate says. + #[test] + fn three_runs_read_give_an_estimate_and_none_of_them_a_promise() { + let mut b = Book::default(); + let p = plan("stabilizer", 2_000_000); + b.runs.insert("stabilizer".into(), vec![timing(2_000_000, 100_000, 10.0); 2]); + assert!(b.wants("stabilizer") && b.wants("exact")); + assert_eq!(b.held(&p).estimate.unwrap_err(), "this command line has not yet metered three stabilizer jobs to estimate from"); + assert_eq!(b.held(&p).watch, Ok(scope()), "no estimate is no bar to a reading"); + b.runs.get_mut("stabilizer").unwrap().push(timing(2_000_000, 100_000, 10.0)); + assert!(!b.wants("stabilizer")); + let (joules, basis) = b.held(&p).estimate.unwrap(); + assert_eq!(joules, 1.0); + assert!(basis.starts_with("an estimate, which promises nothing") && basis.contains("this command line read") && !basis.contains("measured"), "{basis}"); + } + + /// A route is held by a reading only where one can stop it: a method on a device + /// no counter here reads has none, nor a job that can be placed on one, nor a + /// server's run, nor a host that reads nothing. And a reading of part of a run + /// estimates nothing. + #[test] + fn a_route_nothing_can_read_or_stop_has_no_watch() { + let mut b = Book::default(); + let partial = Timing { partial: true, ..timing(1000, 10_000, 5.0) }; + b.runs.insert("statevector_single".into(), vec![partial; 3]); + let gpu = b.held(&plan("statevector_single", 1000)); + assert!(gpu.watch.unwrap_err().contains("the GPU") && gpu.estimate.is_err()); + b.runs.insert("statevector".into(), vec![timing(1000, 10_000, 5.0); 3]); + assert!(b.held(&plan("statevector", 1000)).watch.is_ok()); + b.placed = true; + assert!(b.held(&plan("statevector", 1000)).watch.unwrap_err().contains("an accelerator")); + b.placed = false; + b.embedded = Some("a server's"); + assert_eq!(b.held(&plan("statevector", 1000)).watch.unwrap_err(), "a server's"); + b.embedded = None; + b.unmetered = Some("no counter".into()); + assert_eq!(b.held(&plan("statevector", 1000)).watch.unwrap_err(), "this host reads no energy: no counter"); + assert!(!placed(&json!({ "fabric": "cpu" }))); + assert!(placed(&json!({ "fabric": "accelerator" })) && placed(&json!({ "fabric": ["a", "b"] }))); + assert_eq!(placed(&json!({})), ACCELERATORS); + // Kept as a reading of part of it, by its method or its member. + let d = dir("device"); + let file = d.join("t.json"); + let read = Read { window_us: 10_000, joules: Some(0.05) }; + keep_at(&file, &json!({ "method": "statevector_single", "estimate": { "work": 9 }, "result": {} }), &read).unwrap(); + keep_at(&file, &json!({ "method": "statevector", "estimate": { "work": 9 }, "result": { "fabric": { "key": "gpu0" } } }), &read).unwrap(); + keep_at(&file, &json!({ "method": "statevector", "estimate": { "work": 9 }, "result": { "fabric": { "key": "cpu" } } }), &read).unwrap(); + let back = Book::at(Some(&file)); + assert!(back.runs["statevector_single"][0].partial); + assert_eq!(back.runs["statevector"].iter().map(|t| t.partial).collect::>(), [true, false]); + let _ = std::fs::remove_dir_all(&d); + } + + /// A stopped run's whole figure below the reading that stopped it is no reading; + /// one at or past it is kept. + #[test] + fn a_whole_figure_below_what_stopped_the_run_is_no_reading() { + assert!(no_less_than(json!({ "joules_micro": 1 }), 2.5)["unmetered"].is_string()); + assert_eq!(no_less_than(json!({ "joules_micro": 2_600_000 }), 2.5)["joules_micro"], 2_600_000); + } + + /// On Linux the run's exit wakes the watch at once, not at its next look. + #[cfg(target_os = "linux")] + #[test] + fn a_run_s_exit_wakes_its_watch() { + let mut child = std::process::Command::new("sleep").arg("0.05").spawn().unwrap(); + let began = Instant::now(); + wait_exit_or(child.id(), Duration::from_secs(5)); + assert!(began.elapsed() < Duration::from_secs(2), "{:?}", began.elapsed()); + let _ = child.wait(); + } + + /// A counter that reads nothing once is read again after a spin, not called dead; + /// and a run whose reading is kept nowhere is not read for an estimate. + #[test] + fn a_counter_is_asked_twice_and_a_reading_kept_nowhere_is_not_taken() { + let mut reads = [false, true].into_iter(); + assert!(reads_after(|| reads.next().unwrap(), || {})); + assert!(!reads_after(|| false, || {})); + let b = Book::default(); + let req = json!({ "qasm": "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\nc = measure q;\n", "shots": 10 }); + assert!(!wanted_keeping(&b, &req, 1 << 30, false)); + assert_eq!(wanted_keeping(&b, &req, 1 << 30, true), !cfg!(target_family = "wasm")); + } + + /// A run under a ceiling is a process of its own: at the ceiling it is killed at + /// once and read whole, the receipt saying the longest time between reads; one + /// that finishes is read whole too; one that fails ends the watch, whatever its + /// counter does. + #[test] + fn a_run_in_its_own_process_is_killed_at_its_ceiling_and_read_whole() { + use std::os::unix::fs::PermissionsExt; + if unmetered(true).is_some() { + if cfg!(target_os = "macos") { + panic!("a Mac reads a process's own energy, so this test may not pass by skipping"); + } + return; + } + let d = dir("own-process"); + let script = |name: &str, body: &str| { + let p = d.join(name); + std::fs::write(&p, format!("#!/bin/sh\n{body}\n")).unwrap(); + std::fs::set_permissions(&p, std::fs::Permissions::from_mode(0o755)).unwrap(); + p + }; + let began = Instant::now(); + let Ended::Stopped { stopped, figure } = run_watched(&script("busy", "while :; do :; done"), &json!({}), 0.05).unwrap() else { panic!("a busy run was not stopped") }; + assert!(began.elapsed() < Duration::from_secs(30)); + assert!(stopped.joules >= 0.05 && stopped.read.contains("the longest time between two reads was"), "{stopped:?}"); + let whole = figure["joules_micro"].as_u64().map(|u| u as f64 / 1e6); + assert!(whole.is_some_and(|w| w >= stopped.joules), "read whole after the kill, and no less than what stopped it: {figure} {stopped:?}"); + let Ended::Finished { status, .. } = run_watched(&script("fails", "exit 101"), &json!({}), 1e9).unwrap() else { panic!("a failed run said stopped") }; + assert_eq!(status.code(), Some(101)); + let Ended::Finished { out, status, figure, .. } = run_watched(&script("quick", "read job; echo done"), &json!({ "x": 1 }), 1e9).unwrap() else { panic!("a quick run said stopped") }; + assert!(status.success() && out == b"done\n" && figure.is_object(), "{figure}"); + let _ = std::fs::remove_dir_all(&d); + } + + /// counter costs it nothing. + #[test] + fn a_run_is_read_only_where_something_needs_the_reading() { + let bell = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"; + let req = json!({ "qasm": bell, "shots": 10, "method": "stabilizer" }); + let mut b = Book::default(); + assert!(wanted_keeping(&b, &req, 1 << 30, true), "a method with no runs read"); + b.runs.insert("stabilizer".into(), vec![timing(9, 1000, 1.0); 3]); + assert!(!wanted_keeping(&b, &req, 1 << 30, true), "a method with enough, and no ceiling"); + assert!(wanted(&b, &json!({ "qasm": bell, "shots": 10, "method": "stabilizer", "contract": { "max_joules": 1 } }), 1 << 30)); + assert_eq!(ceiling(&json!({ "contract": { "max_joules": 2.5 } })), Some(2.5)); + // Nothing read, nothing kept: the store is not written for a run with no reading. + let d = dir("nothing"); + let file = d.join("t.json"); + keep_at(&file, &json!({ "method": "stabilizer", "estimate": { "work": 9 }, "result": {} }), &Read { window_us: 10, joules: None }).unwrap(); + assert!(!file.exists()); + let (out, read) = read_run(false, || 7); + assert_eq!((out, read.joules), (7, None)); + let _ = std::fs::remove_dir_all(&d); + } + + /// The wait for a process's counter is in the energy and not in the window: a + /// short run's power is not diluted by it. + #[test] + fn the_wait_for_a_counter_is_in_no_run_s_power() { + let began = Instant::now(); + let read = settled(began, Duration::from_millis(50), || Some(0.01)); + assert!(read.window_us < 40_000, "{read:?}"); + assert!(read.watts().unwrap() > 0.01 / 0.04, "{read:?}"); + // A zero, or a counter that fell, is no reading. + assert_eq!(Read::over(Duration::from_millis(1), Some(0.0)).watts(), None); + assert_eq!(Read::over(Duration::from_millis(1), Some(-1.0)).watts(), None); + } + + /// A package counter, found live and read around a run: over at least a few of + /// its updates, the step it can be short by added, and nothing past a wrap or + /// from a counter that stood still. + #[test] + fn a_package_counter_is_read_over_a_few_of_its_updates() { + let d = dir("packages"); + let zone = d.join("intel-rapl:0"); + std::fs::create_dir_all(&zone).unwrap(); + std::fs::write(zone.join("name"), "package-0\n").unwrap(); + std::fs::write(zone.join("max_energy_range_uj"), "262143328850\n").unwrap(); + std::fs::write(zone.join("energy_uj"), "1000\n").unwrap(); + let (file, going) = (zone.join("energy_uj"), Arc::new(AtomicBool::new(true))); + let ticking = { + let (file, going) = (file.clone(), going.clone()); + std::thread::spawn(move || { + let mut uj = 1000u64; + while going.load(Ordering::Relaxed) { + uj += 500; + // Written whole, so that a read never sees it empty. + let tmp = file.with_extension("tmp"); + std::fs::write(&tmp, format!("{uj}\n")).unwrap(); + std::fs::rename(&tmp, &file).unwrap(); + std::thread::sleep(Duration::from_millis(1)); + } + }) + }; + // The probe is given, not taken: the live probe wants 12 of 15 20 ms intervals + // to see a tick, and this counter is a thread a loaded host starves for whole + // intervals, which is what failed under load and says nothing of what is tested. + let open = || { + let mut p = energy::Packages::open_with_probe(&d, energy::Probe { update_ns: 1_000_000, step_uj: 500 }).unwrap(); + p.probe.update_ns = 1_000_000; + p + }; + let p: &'static energy::Packages = Box::leak(Box::new(open())); + // Every window is over the updates the probe found; a window the writer was + // starved through reads nothing, as it should, so it is taken again. + let reads: Vec = std::iter::repeat_with(|| Around { began: Instant::now(), before: Around::on(p) }.end()).take(50).scan(false, |read, r| (!*read).then(|| { *read = r.joules.is_some(); r })).collect(); + let read = *reads.last().unwrap(); + // A range one millisecond of the most a package draws can pass: the same + // counter, and a window it can have wrapped twice in. + std::fs::write(zone.join("max_energy_range_uj"), "1000000\n").unwrap(); + let short: &'static energy::Packages = Box::leak(Box::new(open())); + let before = Around::on(short); + std::thread::sleep(Duration::from_millis(5)); + let wrapped = Around { began: Instant::now() - Duration::from_millis(5), before }.end(); + going.store(false, Ordering::Relaxed); + ticking.join().unwrap(); + assert!(read.joules.is_some() && read.watts().is_some(), "{read:?}"); + assert!(reads.iter().all(|r| r.window_us >= p.probe.update_ns.saturating_mul(LEAST_UPDATES) / 1000), "{reads:?} {:?}", p.probe); + assert_eq!(wrapped.joules, None, "{wrapped:?}"); + // Standing still, it reads nothing: no reading of zero, and no step alone. + let before = p.read().unwrap(); + assert_eq!(over_updates(Instant::now(), p, &before).joules, None); + // Read live, it adds up what each read found, whatever the last read said. + let count = |uj: u64| std::fs::write(&file, format!("{uj}\n")).unwrap(); + count(5_000_000); + let mut live = p.since(p.read().unwrap()); + count(5_001_000); + assert_eq!(live(), Some(0.001)); + count(5_003_500); + assert_eq!(live(), Some(0.0035)); + std::fs::remove_file(&file).unwrap(); + assert_eq!(live(), None, "a read that fails is none, and costs what was read nothing"); + count(5_004_000); + assert_eq!(live(), Some(0.004)); + let _ = std::fs::remove_dir_all(&d); + } + + /// Readings keep to the build that took them: its version, profile and features + /// are in what they are kept under, beside the machine and its reader. + #[test] + fn readings_are_kept_under_the_machine_reader_and_build() { + let id = identity(); + let profile = if cfg!(debug_assertions) { " debug " } else { " release " }; + assert!(id.contains(env!("CARGO_PKG_VERSION")) && id.contains(profile) && id.contains(std::env::consts::ARCH), "{id}"); + } + + /// Where the file is: an empty value is no value, a relative XDG_CONFIG_HOME is + /// ignored, `off` keeps none, and with no home there is none. + #[test] + fn the_timings_are_kept_where_their_variables_say() { + let env = |pairs: &'static [(&'static str, &'static str)]| move |k: &str| pairs.iter().find(|(n, _)| *n == k).map(|(_, v)| std::ffi::OsString::from(*v)); + assert_eq!(path_from(env(&[("WAI_QUANTUM_TIMINGS", "/t.json"), ("HOME", "/h")])), Some(PathBuf::from("/t.json"))); + assert_eq!(path_from(env(&[("WAI_QUANTUM_TIMINGS", "off"), ("HOME", "/h")])), None); + assert_eq!(path_from(env(&[("XDG_CONFIG_HOME", "/x"), ("HOME", "/h")])), Some(PathBuf::from("/x/wai/quantum-timings.json"))); + for xdg in ["", "relative/dir"] { + let pairs: &'static [(&'static str, &'static str)] = Box::leak(vec![("XDG_CONFIG_HOME", xdg), ("HOME", "/h"), ("WAI_QUANTUM_TIMINGS", "")].into_boxed_slice()); + assert_eq!(path_from(env(pairs)), Some(PathBuf::from("/h/.config/wai/quantum-timings.json")), "{xdg:?}"); + } + assert_eq!(path_from(env(&[("HOME", "")])), None); + // This binary's own tests name their file: none of them reaches a person's. + assert_eq!(path(), None); + } + + /// Threads and processes that finish together each keep their run, and the + /// file reads whole throughout: no shared name to tear, no write to lose. + #[test] + fn runs_that_finish_together_all_keep_theirs() { + let d = dir("together"); + let file = d.join("t.json"); + // No two writes share a temporary name, in a process or between its threads. + let here = scratch(&file); + let there = std::thread::spawn({ + let file = file.clone(); + move || scratch(&file) + }) + .join() + .unwrap(); + assert!(here != there && here != scratch(&file) && here.parent() == file.parent(), "{here:?} {there:?}"); + let writers: Vec<_> = (0..8u64) + .map(|i| { + let file = file.clone(); + std::thread::spawn(move || { + for j in 0..3 { + add(&file, &format!("method-{i}"), &timing(j + 1, 1000, 1.0)).unwrap(); + } + }) + }) + .collect(); + for _ in 0..200 { + if file.exists() { + assert!(matches!(stored(&file).unwrap(), Stored::Store(_)), "the file was read torn"); + } + } + for w in writers { + w.join().unwrap(); + } + let back = Book::at(Some(&file)); + for i in 0..8 { + assert_eq!(back.runs[&format!("method-{i}")].len(), 3, "method-{i}"); + } + let left: Vec<_> = std::fs::read_dir(&d).unwrap().map(|e| e.unwrap().file_name().to_string_lossy().into_owned()).filter(|n| n.ends_with(".tmp")).collect(); + assert!(left.is_empty(), "{left:?}"); + let _ = std::fs::remove_dir_all(&d); + } + + /// A file that is no store of timings is never written over: it is kept aside, + /// and a new store begun. A link to the store stays a link. + #[test] + fn a_file_that_is_no_store_is_kept_and_a_link_stays_a_link() { + let d = dir("aside"); + let file = d.join("t.json"); + for (n, other) in ["{ torn", "{\"schema\":\"wai.quantum.timings/9\",\"methods\":{}}", "{\"someone\":\"else\"}"].iter().enumerate() { + std::fs::write(&file, other).unwrap(); + assert!(Book::at(Some(&file)).runs.is_empty()); + assert_eq!(std::fs::read_to_string(&file).unwrap(), *other, "reading writes nothing"); + add(&file, "exact", &timing(5, 7000, 3.0)).unwrap(); + assert_eq!(std::fs::read_to_string(d.join(format!("t.json.unread-{}", n + 1))).unwrap(), *other); + assert_eq!(Book::at(Some(&file)).runs["exact"].len(), 1); + std::fs::remove_file(&file).unwrap(); + } + #[cfg(unix)] + { + let real = d.join("real.json"); + let link = d.join("link.json"); + std::os::unix::fs::symlink(&real, &link).unwrap(); + add(&link, "exact", &timing(5, 7000, 3.0)).unwrap(); + add(&link, "exact", &timing(5, 7000, 3.0)).unwrap(); + assert!(link.is_symlink() && real.is_file()); + assert_eq!(Book::at(Some(&real)).runs["exact"].len(), 2); + assert_eq!(Book::at(Some(&link)).runs["exact"].len(), 2); + } + let _ = std::fs::remove_dir_all(&d); + } +} diff --git a/wai/wai-quantum-cli/src/main.rs b/wai/wai-quantum-cli/src/main.rs index 225b550ea..44dc85df6 100644 --- a/wai/wai-quantum-cli/src/main.rs +++ b/wai/wai-quantum-cli/src/main.rs @@ -92,6 +92,7 @@ mod converge; mod dap; mod debug; mod estimate; +mod estimates; mod eval; mod discover; mod guide; @@ -318,6 +319,9 @@ enum Command { /// One job a line, each judged as a job's receipt, one JSON verdict a line; the status is 1 when any is not valid #[arg(long, conflicts_with = "history")] lines: bool, + /// For a job under a contract, also run again what can be: its routes priced again at the job's memory, held to the digest it sealed, and its shadow, held to its counts bit for bit + #[arg(long, conflicts_with = "lines")] + recheck: bool, }, /// Show the key this user signs receipts with Key { @@ -564,6 +568,59 @@ struct Job { /// Where the state vector runs (the statevector method): auto (the default: on a member only where the committed measurements show it faster than this host's CPU for the job's size and fusion, otherwise the CPU; `wai-quantum fabric` states the rule and the numbers), cpu, accelerator (the first certified accelerator member that holds the state), or a member's id or key (`wai-quantum fabric` lists them); for a pauli job, accelerator or a member's id or key runs its sum of terms on that member, with the CPU's answers; repeated, the state is split by its top qubits into one partition on each member named, a power of two of them. A member certified bit-exact gives the CPU's answers; a placement this host cannot honour is refused (J013) #[arg(long = "fabric", value_name = "PLACEMENT")] fabric: Vec, + /// The class the answer must be of: bit-exact, exact, single, bounded, estimate, heuristic; measured (a processor's counts), simulated (a provider's simulator's), or any. Under a contract (this, --max-cost, --deadline, --max-joules or --allow-providers) the planner prices every route it can see, runs the cheapest that meets it, and seals its reasoning in the receipt; with nothing to meet it, it refuses with each route's reason (J071), and nothing falls back. Without a class the job keeps the class auto would give + #[arg(long, value_name = "CLASS")] + exactness: Option, + /// The most the run may cost, as 0.50:USD: a route with an unknown cost, or priced in another currency, does not meet it. It confirms nothing: a run that is not free still takes --yes + #[arg(long, value_name = "AMOUNT:CURRENCY", value_parser = max_cost_arg)] + max_cost: Option, + /// When the run must be done by, in seconds: a route whose time is not known does not meet it, and the receipt says whether it was kept (exit 4 when it was not) + #[arg(long = "deadline", value_name = "SECONDS", value_parser = positive_arg)] + deadline: Option, + /// The most energy the run may take, in joules, held by a live reading while it runs: at the ceiling it is stopped, and the receipt says so. A route nothing can read or stop is refused; an estimate beside it promises nothing + #[arg(long, value_name = "JOULES", value_parser = positive_arg)] + max_joules: Option, + /// Let the planner weigh your own providers (`wai-quantum providers list`) beside the methods here: each is asked to estimate the job, and nothing is sent unless one is chosen. A device is chosen only when --exactness measured or any asks for its class. On the job service, which reaches no provider, it changes nothing + #[arg(long)] + allow_providers: bool, + /// The contract itself, as JSON or a file of it: exactness, max_cost, deadline_seconds, max_joules and providers; the options above are set over it + #[arg(long, value_name = "JSON|FILE", value_parser = contract_arg)] + contract: Option, +} + +impl Job { + /// Whether the command line was given a contract, so that a program given on + /// standard input is read once. + fn asks_a_contract(&self) -> bool { + self.contract.is_some() || self.exactness.is_some() || self.max_cost.is_some() || self.deadline.is_some() || self.max_joules.is_some() || self.allow_providers + } +} + +/// A finite number above zero: `inf` or `NaN` would be written as no value at +/// all, and the requirement dropped in silence. +fn positive_arg(s: &str) -> Result { + match s.parse::() { + Ok(x) if x.is_finite() && x > 0.0 => Ok(x), + _ => Err(format!("give a finite number above 0, not {s}")), + } +} + +/// `0.50:USD`: an amount in decimals and its currency. +fn max_cost_arg(s: &str) -> Result { + match s.split_once(':') { + Some((amount, currency)) if wai_quantum::engine::planner::is_decimal(amount) && !currency.is_empty() => Ok(json!({ "amount": amount, "currency": currency })), + _ => Err("give an amount in decimals and its currency, as 0.50:USD".into()), + } +} + +/// A contract as JSON, or the file that holds it. +fn contract_arg(s: &str) -> Result { + let text = if s.trim_start().starts_with('{') { s.to_string() } else { std::fs::read_to_string(s).map_err(|e| format!("{s}: {e}"))? }; + let v: Value = serde_json::from_str(&text).map_err(|e| format!("a contract is a JSON object: {e}"))?; + if !v.is_object() { + return Err("a contract is a JSON object, as {\"exactness\": \"exact\"}".into()); + } + Ok(v) } /// `name=v1,v2,…`: each value a whole number if it reads as one, else a number. @@ -874,19 +931,180 @@ fn request(job: &Job, qasm: String) -> Value { [one] => r["fabric"] = json!(one), many => r["fabric"] = json!(many), } + let mut contract = job.contract.clone(); + let mut set = |k: &str, v: Value| { + contract.get_or_insert_with(|| json!({}))[k] = v; + }; + if let Some(e) = &job.exactness { + set("exactness", json!(e)); + } + if let Some(c) = &job.max_cost { + set("max_cost", c.clone()); + } + if let Some(d) = job.deadline { + set("deadline_seconds", json!(d)); + } + if let Some(j) = job.max_joules { + set("max_joules", json!(j)); + } + if job.allow_providers { + set("providers", json!("allowed")); + } + if let Some(c) = contract { + r["contract"] = c; + } r } -/// What a result says of its energy: the command line does not meter a run. -const UNMETERED: &str = "the command line does not meter a run's energy"; +/// What a result says of its energy, run in this process: no reading of it is +/// sealed (one read in its own process is never complete), and what is read of it +/// is kept for estimates. A run under a ceiling runs in a process of its own, read +/// whole, and its figure is sealed ([`run_under_ceiling`]). +pub(crate) const UNMETERED: &str = "the command line seals no reading of a run in its own process: one read there cannot be read completely, so what it reads of it only estimates later runs"; + +/// The exit status of a run that kept not all its contract asked: a deadline, a +/// ceiling on energy or on cost, as the result states. Its answer is sealed. +pub(crate) const CONTRACT_MISSED: i32 = 4; /// The job body `run` gives, as the service gives it: the request, the plan, /// and the result sealed with `key` ([`job::run`]). +/// A job run here, inside a process with other work in it: a server's, a test's. +/// Nothing can stop one, so a route under a ceiling is refused; nothing is read or +/// kept, since its other threads would be in the reading. pub fn run_here(req: &Value, memory_gb: u64, key: &wai_quantum::ed25519_dalek::SigningKey) -> Result { if catalog::is_set(req) { return wai_quantum::engine::sets::run(req, memory_gb << 30, key, json!({ "unmetered": UNMETERED })); } - job::run(req, memory_gb << 30, key, json!({ "unmetered": UNMETERED })) + let book = estimates::Book::for_job(req, estimates::Surface::Embedded); + let joules = |p: &catalog::Plan| book.held(p); + job::run_with(req, memory_gb << 30, key, json!({ "unmetered": UNMETERED }), Some(&joules)) +} + +/// `req` on `plan` under `ceiling` joules, in a process of its own that this one +/// reads and kills at the ceiling ([`estimates::run_watched`]): sealed with `key`, +/// its whole figure in it, whether it finished or was stopped (then with no answer, +/// and a receipt that says so). `reasoning` is why this route ran. What was read of +/// a run that finished is returned to be kept. +pub(crate) fn run_under_ceiling(req: &Value, plan: &catalog::Plan, reasoning: &Value, ceiling: f64, key: &wai_quantum::ed25519_dalek::SigningKey) -> Result<(Value, estimates::Read), String> { + use wai_quantum::engine::{planner, registry::Registry}; + let exe = std::env::current_exe().map_err(|e| format!("this command line could not find itself to run the job: {e}"))?; + let input = json!({ "request": req, "plan": plan, "reasoning": reasoning }); + match estimates::run_watched(&exe, &input, ceiling)? { + estimates::Ended::Stopped { stopped, figure } => { + eprintln!("note: stopped at its ceiling: a live reading came to {} J, and the run's process was killed there and gave no answer", stopped.joules); + let result = planner::stopped_result(Registry::builtins(), req, plan, reasoning, &stopped); + Ok((job::seal(req, plan, result, key, figure), estimates::Read::default())) + } + estimates::Ended::Finished { out, err, status, figure, read } => { + let r: Value = serde_json::from_slice(&out).map_err(|_| { + let said = String::from_utf8_lossy(&err); + format!("the run's process ended ({status}) with no result{}", said.lines().last().map(|l| format!(": {l}")).unwrap_or_default()) + })?; + if let Some(e) = r.get("error").and_then(Value::as_str) { + return Err(e.to_string()); + } + planner::own_check(req, &r)?; + Ok((job::seal(req, plan, r, key, figure), read)) + } + } +} + +/// A run under a ceiling, in the process [`run_under_ceiling`] started for it: the +/// request, the plan and the reasoning on the first line of standard input, the +/// result, or `{"error"}`, on standard output. It ends with the process that +/// watches it: when that one's end of the pipe closes, however it ended, this one +/// exits (and on Linux the kernel kills it when its parent dies). +fn worker() { + use std::io::{BufRead as _, Read as _}; + use wai_quantum::engine::{planner, registry::Registry}; + die_with_parent(); + let mut stdin = std::io::BufReader::new(std::io::stdin()); + let mut line = String::new(); + let read = stdin.read_line(&mut line); + // The watcher's end of the pipe stays open while it watches: its close is the + // end of this run. + let linked = std::thread::Builder::new().spawn(move || { + let mut rest = [0u8; 64]; + while matches!(stdin.read(&mut rest), Ok(n) if n > 0) {} + std::process::exit(3); + }); + if linked.is_err() { + std::process::exit(3); + } + let out = match read.map_err(|e| e.to_string()).and_then(|_| serde_json::from_str::(&line).map_err(|e| e.to_string())) { + Ok(v) => match serde_json::from_value::(v["plan"].clone()) { + Ok(plan) => planner::run_chosen(Registry::builtins(), &v["request"], &plan, &v["reasoning"]).unwrap_or_else(|e| json!({ "error": e })), + Err(e) => json!({ "error": format!("the job's plan does not read: {e}") }), + }, + Err(e) => json!({ "error": format!("the job did not arrive: {e}") }), + }; + println!("{out}"); + // Off the core before it exits, so that the counter takes in its last stretch + // (on Apple silicon a thread's energy is added as it leaves a core). + std::thread::sleep(std::time::Duration::from_millis(5)); +} + +/// This process killed with its parent: on Linux by the kernel, and on any Unix by +/// noticing the parent changed, within half a second. +fn die_with_parent() { + #[cfg(unix)] + { + // The command line that started this run, as it said: one that is a + // namespace's first process (pid 1) is a parent like any other. + let parent = std::env::var("WAI_QUANTUM_PARENT").ok().and_then(|p| p.parse::().ok()).unwrap_or_else(std::os::unix::process::parent_id); + #[cfg(target_os = "linux")] + { + unsafe extern "C" { + fn prctl(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> i32; + } + /// `PR_SET_PDEATHSIG` and `SIGKILL`. + const PR_SET_PDEATHSIG: i32 = 1; + // SAFETY: it sets this process's own death signal. + let _ = unsafe { prctl(PR_SET_PDEATHSIG, 9, 0, 0, 0) }; + } + if std::os::unix::process::parent_id() != parent { + std::process::exit(3); + } + let watching = std::thread::Builder::new().spawn(move || { + loop { + std::thread::sleep(std::time::Duration::from_millis(100)); + if std::os::unix::process::parent_id() != parent { + std::process::exit(3); + } + } + }); + // A run nothing links to its watcher does not run. + if watching.is_err() { + std::process::exit(3); + } + } +} + +/// The `run` command's job, this process's one run: under a ceiling, in a process of +/// its own read live and killed at the ceiling; otherwise read around where an +/// estimate needs it. What was read is kept. +fn run_read(req: &Value, memory_gb: u64, key: &wai_quantum::ed25519_dalek::SigningKey) -> Result { + use wai_quantum::engine::{planner, registry::Registry}; + if catalog::is_set(req) { + return run_here(req, memory_gb, key); + } + let book = estimates::Book::for_job(req, estimates::Surface::Run); + let joules = |p: &catalog::Plan| book.held(p); + let unmetered = json!({ "unmetered": UNMETERED }); + let Some(ceiling) = estimates::ceiling(req) else { + let wanted = estimates::wanted(&book, req, memory_gb << 30); + let (out, read) = estimates::read_run(wanted, || job::run_with(req, memory_gb << 30, key, unmetered.clone(), Some(&joules))); + let body = out?; + estimates::keep(&body, &read); + return Ok(body); + }; + job::exact_request(req)?; + let reg = Registry::builtins(); + let d = planner::decide(reg, req, &planner::Host::new(memory_gb << 30).with_joules(&joules))?; + let planner::Choice::Local(plan) = &d.choice else { return Err("internal: a provider chosen with none brought".into()) }; + let (body, read) = run_under_ceiling(req, plan, &d.reasoning, ceiling, key)?; + estimates::keep(&body, &read); + Ok(body) } /// What is new in a circuit as a reader takes it in. @@ -983,6 +1201,9 @@ fn print_target(t: &Value) { fn print_job(body: &Value, top: usize) { let r = &body["result"]; let s = |v: &Value| v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()); + if let Some(stopped) = r.get("stopped") { + println!("stopped at its ceiling of {} J: a live reading came to {} J after {} ms ({}), and the run gave no answer", stopped["max_joules"], stopped["joules"], stopped["elapsed_ms"], s(&stopped["read"])); + } if r["format"] == wai_quantum::engine::sets::FORMAT { println!("set {} items, {} done, {} failed", r["count"], r["done"], r["failed"]); for it in r["items"].as_array().into_iter().flatten() { @@ -1089,12 +1310,82 @@ fn print_job(body: &Value, top: usize) { if let Some(ms) = r.get("elapsed_ms") { println!("time {ms} ms"); } + if let Some(p) = r.get("planner") { + print_planner(p); + } + if let Some(sh) = r.get("shadow") { + print_shadow(sh); + } if let Some(key) = r.pointer("/receipt/key").and_then(Value::as_str) { let ok = job::verify(body).map(|(ok, _)| ok).unwrap_or(false); println!("receipt {}, signed by {}", if ok { "verifies" } else { "DOES NOT VERIFY" }, job::did_of(key).unwrap_or_else(|| key.to_string())); } } +/// A planner's reasoning as a person reads it: what was wanted, each route's +/// price or why it was rejected, and the choice. +pub(crate) fn print_planner(p: &Value) { + let s = |v: &Value| v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()); + let from = match p["wanted_from"].as_str() { + Some("contract") => "the contract's", + Some("named") => "the route the job names", + Some("auto") => "what auto would give", + _ => "none named", + }; + println!("contract wants {} ({from}): {}", p["wanted"].as_str().unwrap_or("no class"), s(&p["why"])); + for r in p["routes"].as_array().into_iter().flatten().filter(|r| r["rejected"]["code"] != "not_named") { + let price = &r["price"]; + let time = price["time"]["seconds"].as_f64().map_or_else(|| "time unknown".to_string(), |t| format!("about {t:.3e} s ({})", s(&price["time"]["basis"]))); + let money = if price["money"]["free"] == true { "free".to_string() } else if let Some(a) = price["money"]["amount"].as_str() { format!("{a} {}", s(&price["money"]["currency"])) } else { "cost unknown".to_string() }; + let energy = price["energy"]["joules"].as_f64().map_or_else(String::new, |j| format!(", an estimate of {j} J")); + let priced = if price.is_null() { String::new() } else { format!(" — {money}, {time}{energy}") }; + let left = price["leaves_out"].as_array().filter(|a| !a.is_empty()).map(|a| format!("; leaves out {}", a.iter().map(&s).collect::>().join(", "))).unwrap_or_default(); + let outcome = if let Some(c) = r["rejected"]["code"].as_str() { format!("rejected ({c}: {})", s(&r["rejected"]["why"])) } else { s(&r["outcome"]) }; + println!(" {:<28} {} {}{priced}{left}", s(&r["route"]), s(&r["class"]), outcome); + } + let chosen = p["routes"].as_array().and_then(|a| a.iter().find(|r| r["route"] == p["choice"])); + if let Some(e) = chosen.map(|r| &r["price"]["energy"]) { + if let Some(w) = e["watch"].as_str() { + println!("energy a ceiling here is held by a live reading: {w}"); + } + if let Some(j) = e["joules"].as_f64() { + println!(" {j} J: {}", s(&e["basis"])); + } + } + if p["choice"].is_string() { + println!("stable {}", if p["stable"]["choice"] == true { "this choice depends on nothing of this host" } else { "this choice depends on this host (its providers, a GPU, or its energy estimate)" }); + } + if let Some(sh) = p.get("shadow").filter(|sh| sh["route"].is_null()) { + println!("shadow none possible: {}", s(&sh["why"])); + } else if let Some(sh) = p.get("shadow").filter(|_| p.get("kept").is_none()) { + println!("shadow {} will run beside it ({})", s(&sh["route"]), s(&sh["class"])); + } + for (k, v) in p["kept"].as_object().into_iter().flatten() { + let held = match v["kept"].as_bool() { + Some(true) => "kept".to_string(), + Some(false) => "MISSED".to_string(), + None => "not known".to_string(), + }; + println!("kept {k}: {held}"); + } +} + +/// A shadow as a person reads it. +pub(crate) fn print_shadow(sh: &Value) { + let s = |v: &Value| v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()); + if sh["ran"] == true { + let d = &sh["distance"]; + let said = if d["computed"] == true { + format!("total variation {:.4} from the provider's counts (these shots alone leave at most about {:.4}); Hellinger fidelity {:.4}", d["total_variation"].as_f64().unwrap_or(f64::NAN), d["sampling_tvd_bound"].as_f64().unwrap_or(f64::NAN), d["hellinger_fidelity"].as_f64().unwrap_or(f64::NAN)) + } else { + format!("no distance: {}", s(&d["why"])) + }; + println!("shadow {} ({}): {said}", s(&sh["route"]), s(&sh["accuracy"]["class"])); + } else { + println!("shadow none: {} ({})", s(&sh["why"]), s(&sh["code"])); + } +} + fn load_key(k: &KeyArgs) -> keys::Key { let key = keys::load(k.key.as_deref(), k.demo_key).unwrap_or_else(|e| die(&e)); keys::notes(&key); @@ -1181,6 +1472,9 @@ fn convert(file: Option<&Path>, to: wai_quantum::engine::formats::Format, profil fn main() { // The help a parse prints is in the person's language, so the language is read first. let args: Vec = std::env::args().collect(); + if args.get(1).map(String::as_str) == Some(estimates::WORKER) { + return worker(); + } let loc = locale::resolve(locale::arg_lang(&args).as_deref()); locale::set(loc); let cli = Cli::from_arg_matches(&locale::localize(Cli::command(), loc).get_matches_from(&args)).unwrap_or_else(|e| e.exit()); @@ -1188,11 +1482,11 @@ fn main() { let _ = FROM.set(cli.from); match cli.command { #[cfg(feature = "providers")] - Command::Run { job, out, key, provider } if provider.provider.is_some() => providers::run(&job, &out, &key, &provider), + Command::Run { job, out, key, provider } if provider.provider.is_some() || job.allow_providers => providers::run(&job, &out, &key, &provider), Command::Run { job, out, key, .. } => { let req = job_request(&job).unwrap_or_else(|e| die(&e)); let k = load_key(&key); - let body = match run_here(&req, job.memory_gb, &k.key) { + let body = match run_read(&req, job.memory_gb, &k.key) { Ok(b) => b, // A job that asked for a verdict is refused with one. Err(e) if wai_quantum::engine::verdict::asked(&req) || job.repair => { @@ -1218,13 +1512,19 @@ fn main() { Some(items) => items.iter().map(|i| i.pointer("/result/verdict/holds").and_then(Value::as_bool)).collect(), None => vec![body.pointer("/result/verdict/holds").and_then(Value::as_bool)], }; - std::process::exit(if holds.contains(&Some(false)) { + let status = if holds.contains(&Some(false)) { 1 } else if holds.iter().all(|h| *h == Some(true)) { 0 } else { 2 - }); + }; + if status != 0 { + std::process::exit(status); + } + } + if wai_quantum::engine::planner::missed(&body["result"]) { + std::process::exit(CONTRACT_MISSED); } } Command::Plan { job, json } if !job.programs.is_empty() || !job.sweep.is_empty() => { @@ -1243,6 +1543,31 @@ fn main() { } } } + #[cfg(feature = "providers")] + Command::Plan { job, json } if job.allow_providers => providers::plan(&job, json), + Command::Plan { job, json } if job.asks_a_contract() => { + use wai_quantum::engine::{planner, refusal, registry::Registry}; + let req = job_request(&job).unwrap_or_else(|e| die(&e)); + let book = estimates::Book::for_job(&req, estimates::Surface::Run); + let joules = |p: &catalog::Plan| book.held(p); + let c = planner::consider(Registry::builtins(), &req, &planner::Host::new(job.memory_gb << 30).with_joules(&joules)).unwrap_or_else(|e| die(&e)); + if json { + let mut v = c.plan.as_ref().map_or_else(|| json!({}), |p| serde_json::to_value(p).unwrap_or(Value::Null)); + if let Some(e) = &c.refusal { + v["refused"] = refusal::refusal_json(e); + } + v["planner"] = c.reasoning.clone(); + println!("{v}"); + } else { + print_planner(&c.reasoning); + if let Some(p) = &c.plan { + println!("memory {:.1} MiB at most", p.memory_bytes as f64 / (1u64 << 20) as f64); + } + } + if let Some(e) = &c.refusal { + die(e); + } + } Command::Plan { job, json } => { let req = job_request(&job).unwrap_or_else(|e| die(&e)); let p = catalog::plan(&req, job.memory_gb << 30).unwrap_or_else(|e| die(&e)); @@ -1399,7 +1724,7 @@ fn main() { } #[cfg(feature = "service")] Command::Task { cmd, args } => task::main(cmd, &args), - Command::Verify { file, history: hist, json: as_json, lines } => { + Command::Verify { file, history: hist, json: as_json, lines, recheck } => { let bytes = read_bytes(file.as_deref()).unwrap_or_else(|e| die(&e)); let src = match String::from_utf8(bytes) { Ok(s) => s, @@ -1476,6 +1801,7 @@ fn main() { } } else if as_json || (v.get("request").is_some() && v.get("result").is_some()) { let c = job::check_text(&src); + let again = recheck.then(|| wai_quantum::engine::planner::recheck(wai_quantum::engine::registry::Registry::builtins(), &v).unwrap_or_else(|e| die(&e))); if as_json { // A set's verdict also says what the engine checks past its receipt. let mut said = if set { job::verdict_of_text(&src).unwrap_or_else(|_| c.to_json()) } else { c.to_json() }; @@ -1487,14 +1813,30 @@ fn main() { } said["history"] = r; } + if let Some(a) = &again { + said["recheck"] = a.clone(); + } println!("{said}"); - if said["valid"] != true { + if said["valid"] != true || again.as_ref().is_some_and(|a| a["holds"] != true) { std::process::exit(1); } return; } let mut ok = c.valid(); print_check(&c); + if let Some(a) = &again { + let said = |x: &Value| match (x["checked"].as_bool(), x["same"].as_bool()) { + (Some(true), Some(true)) => "the same".to_string(), + (Some(true), _) => "NOT THE SAME".to_string(), + _ => format!("not checked: {}", x["why"].as_str().unwrap_or("")), + }; + println!("priced again {}", said(&a["priced"])); + println!("shadow again {}", said(&a["shadow"])); + if a["engine"]["same"] != true { + println!("engine sealed by {}, rechecked by {}: a price may differ between them", a["engine"]["sealed_by"].as_str().unwrap_or("another"), a["engine"]["this"].as_str().unwrap_or("")); + } + ok &= a["holds"] == true; + } if set { let s = wai_quantum::engine::sets::verify(&v); let yes = |b: &Value| if *b == true { "yes" } else { "NO" }; @@ -1651,6 +1993,18 @@ fn print_check(c: &job::Check) { if broken.is_empty() { println!("rules {}", if rules.is_empty() { "every rule a verifier checks holds (wai/extensions/quantum-providers.md section 8.4)".to_string() } else { format!("BROKEN: {}", rules.join(", ")) }); } + if let Some(p) = &c.planner { + let s = |v: &Value| v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()); + println!("contract wanted {}, given {}, by {}", p["wanted"].as_str().unwrap_or("no class"), s(&p["class"]), s(&p["choice"])); + for (k, v) in p["kept"].as_object().into_iter().flatten() { + println!("kept {k}: {}", match v["kept"].as_bool() { Some(true) => "kept", Some(false) => "MISSED", None => "not known" }); + } + if p["shadow_ran"] == true { + println!("shadow total variation {} from a classical method's counts", s(&p["shadow_total_variation"])); + } else if p["shadow_ran"] == false { + println!("shadow none could be run; the result says why"); + } + } let Some(p) = &c.provider else { return }; let s = |v: &Value| v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()); let class = s(&p["class"]); @@ -1738,7 +2092,7 @@ mod tests { fn job(qasm: &str) -> (Job, String) { ( - Job { file: None, shots: None, seed: None, method: None, observables: vec![], amplitudes: vec![], noise: vec![], options: vec![], memory_gb: 1, history: None, compile: None, target: None, intent: vec![], verdict: false, repair: false, max_iterations: None, programs: vec![], sweep: vec![], mitigate: None, pulse: None, params: vec![], fabric: vec![] }, + Job { file: None, shots: None, seed: None, method: None, observables: vec![], amplitudes: vec![], noise: vec![], options: vec![], memory_gb: 1, history: None, compile: None, target: None, intent: vec![], verdict: false, repair: false, max_iterations: None, programs: vec![], sweep: vec![], mitigate: None, pulse: None, params: vec![], fabric: vec![], exactness: None, max_cost: None, deadline: None, max_joules: None, allow_providers: false, contract: None }, qasm.to_string(), ) } @@ -1876,6 +2230,35 @@ mod tests { } assert!(Cli::try_parse_from(["wai-quantum", "debug", "p.qasm", "--branches", "--to", "3"]).is_err()); assert!(matches!(Cli::try_parse_from(["wai-quantum", "dap"]).unwrap().command, Command::Dap)); + // A contract, from its options, set over a contract given whole. + match Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--exactness", "exact", "--max-cost", "0.50:USD", "--deadline", "30", "--max-joules", "5", "--allow-providers", "--contract", "{\"exactness\": \"any\", \"deadline_seconds\": 1}"]).unwrap().command { + Command::Run { job, .. } => { + assert!(job.asks_a_contract()); + let r = request(&job, "qubit q;".into()); + assert_eq!(r["contract"], json!({ "exactness": "exact", "max_cost": { "amount": "0.50", "currency": "USD" }, "deadline_seconds": 30.0, "max_joules": 5.0, "providers": "allowed" }), "{r}"); + } + _ => panic!("not run"), + } + match Cli::try_parse_from(["wai-quantum", "run", "p.qasm"]).unwrap().command { + Command::Run { job, .. } => assert!(!job.asks_a_contract() && request(&job, "qubit q;".into()).get("contract").is_none()), + _ => panic!("not run"), + } + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--max-cost", "0.50"]).is_err(), "a ceiling has its currency"); + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--max-cost", "1e3:USD"]).is_err(), "an amount in decimals"); + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--contract", "[]"]).is_err(), "a contract is an object"); + // A ceiling or a deadline that is no finite number above zero would be + // written as nothing, and dropped in silence: refused. + for (flag, v) in [("--deadline", "inf"), ("--deadline", "0"), ("--deadline", "-1"), ("--max-joules", "NaN"), ("--max-joules", "infinity")] { + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", flag, v]).is_err(), "{flag} {v}"); + } + #[cfg(feature = "providers")] + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--confirm", "abc"]).is_err(), "a word confirms a routed run only"); + #[cfg(feature = "providers")] + { + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--dry-run"]).is_err(), "a dry run of what"); + assert!(Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--yes", "--allow-providers"]).is_ok()); + assert!(Cli::try_parse_from(["wai-quantum", "plan", "p.qasm", "--allow-providers"]).is_ok()); + } match Cli::try_parse_from(["wai-quantum", "run", "p.qasm", "--target", "synthetic-line-5"]).unwrap().command { Command::Run { job, .. } => assert_eq!(job.target.as_deref(), Some("synthetic-line-5")), _ => panic!("not run"), diff --git a/wai/wai-quantum-cli/src/mcp.rs b/wai/wai-quantum-cli/src/mcp.rs index d92532e9e..b7864ae20 100644 --- a/wai/wai-quantum-cli/src/mcp.rs +++ b/wai/wai-quantum-cli/src/mcp.rs @@ -60,7 +60,7 @@ pub(crate) fn schemas() -> &'static Registry { /// The schema each tool's answer follows, by its file and place. fn output_of(tool: &str) -> Option<&'static str> { Some(match tool { - "run_quantum_circuit" | "run_on_provider" => "job.v1.json", + "run_quantum_circuit" | "run_on_provider" | "run_routed" => "job.v1.json", "get_provider_job" | "cancel_provider_job" => "local-tools.v1.json#/$defs/provider_job", "list_provider_jobs" => "local-tools.v1.json#/$defs/provider_jobs", "plan_quantum_circuit" => "plan.v1.json", @@ -102,6 +102,7 @@ fn output_of(tool: &str) -> Option<&'static str> { "taste_next" => "local-tools.v1.json#/$defs/taste_next", "providers_list" => "local-tools.v1.json#/$defs/providers_list", "provider_estimate" => "local-tools.v1.json#/$defs/provider_estimate", + "plan_routes" => "local-tools.v1.json#/$defs/routed", "qec_code" | "qec_decode" | "qec_threshold" => "qec.v1.json", "pulse_schedule" | "pulse_check" => "pulse.v1.json", "gradient_qasm" | "optimize_qasm" | "vqe_ground_state" | "qaoa_maxcut" | "build_algorithm" => "algorithms.v1.json", @@ -131,7 +132,8 @@ fn job_schema() -> Value { "repair": { "description": "Repair the program first, on the lines its diagnostics flag alone (as repair_qasm does): true, or the choices {\"max_iterations\": N, \"dyadic_bits\": K, \"sizes\": {\"q\": 3}}. The result's \"repaired\" holds the program that ran and each repair." }, "mitigate": wai_quantum::engine::mitigate::schema(), "pulse": wai_quantum::engine::pulse::options_schema(), - "params": { "type": "object", "additionalProperties": { "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050)." } + "params": { "type": "object", "additionalProperties": { "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read. A parameter left without one is refused (J050)." }, + "contract": wai_quantum::engine::planner::contract_schema() } }) } @@ -264,13 +266,13 @@ fn core_tools() -> Value { { "name": "run_quantum_circuit", "title": "Run a quantum program here", - "description": "Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more.", + "description": "Run an OpenQASM program on this machine, planned as the quantum job service plans it: measurement counts, Pauli expectation values and/or amplitudes, the method chosen and why, its accuracy class, and a receipt signed with this user's key. Give `contract` (the class wanted, a deadline) and the planner prices every method here, runs the cheapest that meets it, seals its reasoning under `planner`, and refuses (J071) rather than fall back to less; this tool reaches no provider, and plan_routes and run_routed do. Give `intent` (an exact distribution, or a reference program it must equal or whose state it must prepare) and the engine checks it with the run. Every answer carries `verdict`: the level the engine checked to (proof, evidence, executed, parsed, refused), whether the intent holds and a plain statement, sealed in the receipt. Quote the verdict and the numbers; do not estimate them or claim more.", "inputSchema": job_schema(), }, { "name": "plan_quantum_circuit", "title": "Plan a quantum program", - "description": "The method a program would run on and why, the memory and work it would take, without running it.", + "description": "The method a program would run on and why, the memory and work it would take, without running it. With a contract, every route's price or reason for rejection under planner, or the refusal (J071) when no route meets it.", "inputSchema": job_schema(), }, { @@ -352,8 +354,8 @@ fn core_tools() -> Value { { "name": "verify_quantum_result", "title": "Check a result's receipt", - "description": "Whether a job's receipt seals its request and its result, as run_quantum_circuit or the job service returns them, and every rule of its form holds (`reasons` names what does not), and which key signed it.", - "inputSchema": { "type": "object", "required": ["job"], "properties": { "job": { "type": ["object", "string"], "description": "The job's text as it was given (preferred: read as the protocol reads it, so a member named twice or a number past what a parsed job keeps is seen), or the job: {\"request\": ..., \"result\": ...}, the result carrying its receipt." } } }, + "description": "Whether a job's receipt seals its request and its result, as run_quantum_circuit or the job service returns them, and every rule of its form holds (`reasons` names what does not), and which key signed it; for a job under a contract, every route's outcome and the choice recomputed from what it states, and with recheck its routes priced again and its shadow run again.", + "inputSchema": { "type": "object", "required": ["job"], "properties": { "job": { "type": ["object", "string"], "description": "The job's text as it was given (preferred: read as the protocol reads it, so a member named twice or a number past what a parsed job keeps is seen), or the job: {\"request\": ..., \"result\": ...}, the result carrying its receipt." }, "recheck": { "type": "boolean", "description": "For a job under a contract: its routes priced again at the job's memory, held to the digest it sealed, and its shadow run again, held to its counts bit for bit." } } }, }, { "name": "discover_evaluate", @@ -593,7 +595,14 @@ fn call(name: &str, args: &Value, memory_gb: u64, key: &SigningKey, client: &Cli } "plan_quantum_circuit" => { qasm()?; - catalog::plan(&with_target()?, memory_gb << 30).map(|p| serde_json::to_value(p).unwrap_or(Value::Null)) + let req = with_target()?; + if wai_quantum::engine::planner::has_contract(&req) { + let book = crate::estimates::Book::for_job(&req, crate::estimates::Surface::Embedded); + let joules = |p: &catalog::Plan| book.held(p); + let host = wai_quantum::engine::planner::Host::new(memory_gb << 30).with_joules(&joules); + return wai_quantum::engine::planner::plan_value_on(wai_quantum::engine::registry::Registry::builtins(), &req, &host); + } + catalog::plan(&req, memory_gb << 30).map(|p| serde_json::to_value(p).unwrap_or(Value::Null)) } "lint_qasm" => Ok(job::lint(qasm()?)), "critique_qasm" => Ok(critique::critique(qasm()?)), @@ -633,7 +642,11 @@ fn call(name: &str, args: &Value, memory_gb: u64, key: &SigningKey, client: &Cli } return if parsed["result"]["format"] == wai_quantum::engine::estimate::FORMAT { wai_quantum::engine::estimate::verify(&parsed) } else { Ok(wai_quantum::engine::variational::verify(&parsed)) }; } - return job::verdict_of_text(text).or_else(|_| Ok(job::verdict_of(&job::check_text(text)))); + let mut said = job::verdict_of_text(text).unwrap_or_else(|_| job::verdict_of(&job::check_text(text))); + if args.get("recheck") == Some(&Value::Bool(true)) && parsed.is_object() { + said["recheck"] = wai_quantum::engine::planner::recheck(wai_quantum::engine::registry::Registry::builtins(), &parsed)?; + } + return Ok(said); } if given["result"]["format"] == wai_quantum::engine::estimate::FORMAT { return wai_quantum::engine::estimate::verify(given); @@ -641,7 +654,11 @@ fn call(name: &str, args: &Value, memory_gb: u64, key: &SigningKey, client: &Cli if given["result"]["schema"] == wai_quantum::engine::schema::ALGORITHMS { return Ok(wai_quantum::engine::variational::verify(given)); } - job::verdict(given) + let mut said = job::verdict(given)?; + if args.get("recheck") == Some(&Value::Bool(true)) { + said["recheck"] = wai_quantum::engine::planner::recheck(wai_quantum::engine::registry::Registry::builtins(), given)?; + } + Ok(said) } "list_methods" => Ok(json!({ "methods": catalog::describe(memory_gb << 30) })), "list_fabric" => Ok(wai_quantum::engine::fabric::list(memory_gb << 30)), @@ -1083,7 +1100,7 @@ mod tests { #[allow(unused_mut)] let mut want = vec!["run_quantum_circuit", "plan_quantum_circuit", "lint_qasm", "repair_qasm", "critique_qasm", "check_equivalent", "convert_program", "improve_qasm", "classical_shortcuts", "compile_qasm", "estimate_resources", "draw_circuit", "debug_step", "debug_branches", "verify_quantum_result", "discover_evaluate", "discover_submit", "discover_archive", "novelty_qasm", "discover_novelty", "rewrite_qasm", "converge_cohort", "converge_history", "study_measure", "study_cohort", "taste_rank", "taste_next", "history_commit", "history_changes", "history_blame", "history_log", "list_methods", "list_fabric", "list_components", "qasm_diagnostics", "list_targets", "show_target", "run_on_target", "qec_code", "qec_decode", "qec_threshold", "pulse_schedule", "pulse_check", "gradient_qasm", "optimize_qasm", "vqe_ground_state", "qaoa_maxcut", "build_algorithm"]; #[cfg(feature = "providers")] - want.extend(["providers_list", "provider_estimate", "run_on_provider", "get_provider_job", "cancel_provider_job", "list_provider_jobs"]); + want.extend(["providers_list", "provider_estimate", "run_on_provider", "plan_routes", "run_routed", "get_provider_job", "cancel_provider_job", "list_provider_jobs"]); assert_eq!(names, want); let run = handle( &json!({ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "run_quantum_circuit", "arguments": { "qasm": "OPENQASM 3.0; qubit[2] q; h q[0]; cx q[0], q[1];", "observables": ["Z0 Z1"] } } }), @@ -1689,6 +1706,19 @@ mod tests { let t = Target::new("lab", Kind::Process, Box::new(OpenProvider::new(Local(move |m: &Value| r.handle(m, None)))), None); let req = json!({ "qasm": bell, "shots": 50, "provider": "lab" }); hold("provider_estimate", &pjob::plan(&t, &req).unwrap().json, &mut called); + // Under a contract: the provider's plan with the reasoning, a route weighed, and each of them run. + let under = json!({ "qasm": bell, "shots": 50, "provider": "lab", "contract": { "providers": "allowed", "exactness": "simulated" } }); + hold("provider_estimate", &pjob::plan(&t, &under).unwrap().json, &mut called); + hold("run_on_provider", &pjob::run(&t, &under, false, &key(), wait, |_| {}).unwrap(), &mut called); + let routed_to_it = json!({ "qasm": bell, "shots": 50, "contract": { "exactness": "simulated", "providers": "allowed" } }); + let routed = pjob::route(std::slice::from_ref(&t), &routed_to_it, 1 << 30).unwrap(); + hold("plan_routes", &routed.json(), &mut called); + let mut sent = pjob::start_routed(&t, &routed, &routed_to_it, None, &ledger).unwrap(); + hold("run_routed", pjob::check(&t, &mut sent, &key(), &ledger).unwrap().job(), &mut called); + let here = json!({ "qasm": bell, "shots": 50, "contract": { "exactness": "exact", "providers": "allowed" } }); + let routed = pjob::route(std::slice::from_ref(&t), &here, 1 << 30).unwrap(); + hold("plan_routes", &routed.json(), &mut called); + hold("run_routed", &pjob::run_routed_here(&routed, &here, &key(), json!({ "unmetered": "a test" })).unwrap(), &mut called); hold("run_on_provider", &pjob::run(&t, &req, false, &key(), wait, |_| {}).unwrap(), &mut called); // A job still at the provider, then finished, then one cancelled, each in the job's form. let waiting = std::sync::Arc::new(Reference::new(Config { polls: 1, ..Config::default() }).unwrap()); diff --git a/wai/wai-quantum-cli/src/providers.rs b/wai/wai-quantum-cli/src/providers.rs index 0ea7f2e0e..4e1ef6846 100644 --- a/wai/wai-quantum-cli/src/providers.rs +++ b/wai/wai-quantum-cli/src/providers.rs @@ -91,19 +91,23 @@ impl Books { /// `run`'s flags for a provider. #[derive(Args, Clone, Default)] +#[command(group = clap::ArgGroup::new("via_provider").args(["provider", "allow_providers"]).multiple(true))] pub struct RunArgs { /// Run on one of your own providers (`wai-quantum providers list`) instead of here: a device answers counts, sealed as measured on it, or as simulated when the provider's device is a simulator #[arg(long, value_name = "NAME")] pub provider: Option, - /// With --provider: the plan (the exact compile to the device's gates and its check by simulation) and the provider's estimate; nothing is submitted - #[arg(long, requires = "provider")] + /// With --provider or --allow-providers: the plan (the exact compile to the device's gates and its check by simulation) and the provider's estimate, or every route's price or reason; nothing is submitted + #[arg(long, requires = "via_provider")] pub dry_run: bool, - /// With --provider: confirm a run that is not free, or whose cost is unknown; without it such a run is refused (exit 3) - #[arg(long, requires = "provider")] + /// With --provider or --allow-providers: confirm a run that is not free, or whose cost is unknown; without it such a run is refused (exit 3). A cost ceiling is no confirmation + #[arg(long, requires = "via_provider")] pub yes: bool, - /// With --provider: send the job and answer with its handle, without waiting (`wai-quantum providers collect`) - #[arg(long, requires = "provider")] + /// With --provider or --allow-providers: send the job and answer with its handle, without waiting (`wai-quantum providers collect`) + #[arg(long, requires = "via_provider")] pub no_wait: bool, + /// With --allow-providers: confirm the run the planner chose when it is not free, by the word its dry run gave for that route, its estimate and its program; a route, an estimate or a program that changed since is refused. --yes confirms only a provider you name + #[arg(long, value_name = "WORD", requires = "allow_providers")] + pub confirm: Option, } #[derive(Subcommand)] @@ -290,25 +294,103 @@ fn sleeper() -> impl Fn(Duration) + 'static { } } -/// `run --provider`: the job on the person's provider, or its dry run. -pub fn run(job: &Job, out: &Output, key: &KeyArgs, args: &RunArgs) { - let name = args.provider.as_deref().unwrap_or_default(); - let mut req = job_request(job).unwrap_or_else(|e| die(&e)); - req["provider"] = json!(name); +/// Every provider the person has, each ready to be asked, with those that +/// cannot be opened as routes that say why. +fn targets(reg: &Registry, stores: &Stores, job_bytes: u64) -> (Vec, Vec) { + let (mut open, mut closed) = (Vec::new(), Vec::new()); + for e in reg.entries() { + match registry::open(e, stores) { + Ok(t) => open.push(t.with_job_bytes(job_bytes)), + Err(why) => closed.push(wai_quantum::engine::planner::Quote::cannot(e.name.clone(), why)), + } + } + (open, closed) +} + +/// `plan --allow-providers`: every route, the person's providers among them, +/// priced; each provider is asked for its estimate, and nothing is sent. +pub fn plan(job: &Job, as_json: bool) { + let req = job_request(job).unwrap_or_else(|e| die(&e)); let (reg, stores) = load(); - let t = registry::open(entry(®, name).unwrap_or_else(|e| die(&e)), &stores).unwrap_or_else(|e| die(&e)); + let (open, closed) = targets(®, &stores, job.memory_gb << 30); + let book = crate::estimates::Book::for_job(&req, crate::estimates::Surface::Run); + let routed = counted(pjob::route_with(&open, closed, &req, job.memory_gb << 30, Some(&|p: &wai_quantum::engine::catalog::Plan| book.held(p))).unwrap_or_else(|e| die(&e.to_string()))); + if as_json { + println!("{}", routed.json()); + } else { + print_routed(&routed); + } +} + +/// `routed`, its word the one for the next run of its job by the person's ledger. +fn counted(routed: pjob::Routed) -> pjob::Routed { + match Ledger::load_default() { + Ok(l) => routed.counted(&l), + Err(_) => routed, + } +} + +/// A routed plan as a reader takes it in: the planner's reasoning, and, where the +/// route chosen is not free, the word that confirms that route at that estimate. +fn print_routed(routed: &pjob::Routed) { + crate::print_planner(&routed.reasoning); + if let Some(says) = routed.json().pointer("/confirm/says").and_then(Value::as_str) { + println!("confirm {says}"); + } +} + +/// `run --allow-providers`: the route the planner chose, here or on a provider. +fn run_routed(job: &Job, out: &Output, key: &KeyArgs, args: &RunArgs) { + let req = job_request(job).unwrap_or_else(|e| die(&e)); + let (reg, stores) = load(); + let (open, closed) = targets(®, &stores, job.memory_gb << 30); + let book = crate::estimates::Book::for_job(&req, crate::estimates::Surface::Run); + let routed = counted(pjob::route_with(&open, closed, &req, job.memory_gb << 30, Some(&|p: &wai_quantum::engine::catalog::Plan| book.held(p))).unwrap_or_else(|e| die(&e.to_string()))); if args.dry_run { - let p = pjob::plan(&t, &req).unwrap_or_else(|e| die(&e.to_string())); if out.json { - println!("{}", p.json); + println!("{}", routed.json()); } else { - print_plan(&p.json); + print_routed(&routed); } return; } + // A route the person was not shown is not theirs to confirm with a bare yes. + if args.yes { + die("--yes confirms a run on a provider you name (--provider); a route the planner chooses is confirmed by the word its dry run gives for it: run with --dry-run, then --confirm WORD"); + } let k = load_key(key); + let Some(name) = routed.provider().map(str::to_string) else { + let unmetered = json!({ "unmetered": crate::UNMETERED }); + let run = || pjob::run_routed_here(&routed, &req, &k.key, unmetered.clone()).map_err(|e| e.to_string()); + let (body, read) = match (crate::estimates::ceiling(&req), &routed.choice) { + (Some(ceiling), wai_quantum::engine::planner::Choice::Local(plan)) => match crate::run_under_ceiling(&req, plan, &routed.reasoning, ceiling, &k.key) { + Ok((body, read)) => (Ok(body), read), + Err(e) => (Err(e), crate::estimates::Read::default()), + }, + _ => crate::estimates::read_run(crate::estimates::wanted(&book, &req, job.memory_gb << 30), run), + }; + let body = body.unwrap_or_else(|e| die(&e)); + crate::estimates::keep(&body, &read); + if out.json { + println!("{body}"); + } else { + print_job(&body, out.top); + } + if wai_quantum::engine::planner::missed(&body["result"]) { + std::process::exit(crate::CONTRACT_MISSED); + } + return; + }; + let t = open.iter().find(|t| t.name == name).unwrap_or_else(|| die("internal: the planner chose a provider it was not given")); let ledger = Ledger::load_default().unwrap_or_else(|e| die(&e)); - let mut ticket = match pjob::start(&t, &req, args.yes, &ledger) { + let ticket = pjob::start_routed(t, &routed, &req, args.confirm.as_deref(), &ledger); + follow_started(t, ticket, &ledger, &k.key, out, args, &name); +} + +/// A job sent, followed as `run` follows one: refused, or left at the provider, +/// or sealed and shown. +fn follow_started(t: &Target, started: Result, ledger: &Ledger, key: &SigningKey, out: &Output, args: &RunArgs, name: &str) { + let mut ticket = match started { Ok(ticket) => ticket, Err(JobError::Unconfirmed { plan, message }) => { if out.json { @@ -326,8 +408,38 @@ pub fn run(job: &Job, out: &Output, key: &KeyArgs, args: &RunArgs) { return; } eprintln!("note: recorded as {h}: if this stops, the job goes on at {name}, and `wai-quantum providers collect {h}` comes back to it", h = ticket.handle()); - let progress = pjob::follow(&t, &mut ticket, &k.key, &ledger, WAIT, sleeper()).unwrap_or_else(|e| die(&e.to_string())); - std::process::exit(show(&progress, out)); + let progress = pjob::follow(t, &mut ticket, key, ledger, WAIT, sleeper()).unwrap_or_else(|e| die(&e.to_string())); + let status = show(&progress, out); + if status == 0 && wai_quantum::engine::planner::missed(&progress.job()["result"]) { + std::process::exit(crate::CONTRACT_MISSED); + } + std::process::exit(status); +} + +/// `run --provider`: the job on the person's provider, or its dry run; with +/// `--allow-providers` and none named, the route the planner chooses. +pub fn run(job: &Job, out: &Output, key: &KeyArgs, args: &RunArgs) { + if args.provider.is_none() { + return run_routed(job, out, key, args); + } + let name = args.provider.as_deref().unwrap_or_default(); + let mut req = job_request(job).unwrap_or_else(|e| die(&e)); + req["provider"] = json!(name); + let (reg, stores) = load(); + let t = registry::open(entry(®, name).unwrap_or_else(|e| die(&e)), &stores).unwrap_or_else(|e| die(&e)).with_job_bytes(job.memory_gb << 30); + if args.dry_run { + let p = pjob::plan(&t, &req).unwrap_or_else(|e| die(&e.to_string())); + if out.json { + println!("{}", p.json); + } else { + print_plan(&p.json); + } + return; + } + let k = load_key(key); + let ledger = Ledger::load_default().unwrap_or_else(|e| die(&e)); + let started = pjob::start(&t, &req, args.yes, &ledger); + follow_started(&t, started, &ledger, &k.key, out, args, name); } /// A job as the command line shows it, and the exit status that says where it @@ -616,6 +728,7 @@ fn provider_schema(extra: Value) -> Value { "inputs": { "type": "object", "additionalProperties": { "type": "integer" }, "description": "A generator's inputs' values, as {\"n\": 5}." }, "shots": { "type": "integer", "minimum": 1, "description": "Shots (default 1024)." }, "seed": { "type": "integer", "minimum": 0, "description": "A seed, for a provider that is a seeded simulator; a device ignores it." }, + "contract": wai_quantum::engine::planner::contract_schema(), } }); if let (Some(p), Some(e)) = (s["properties"].as_object_mut(), extra.as_object()) { @@ -646,6 +759,18 @@ pub fn mcp_tools() -> Vec { "inputSchema": provider_schema(json!({ "confirm_cost": { "type": "boolean", "description": "true only when the person has agreed to this run's cost. A run that is not free is refused without it." } })), "execution": { "taskSupport": "optional" }, }), + json!({ + "name": "plan_routes", + "title": "Weigh a contract against every route", + "description": "Every route a job could take under its contract: the methods on this machine and each of the person's own providers, each with its price or why it was rejected, what a provider's estimate leaves out, and the route the planner would choose: the cheapest that meets the contract, or the refusal (J071) with every route's reason. Each provider is asked to describe its device and estimate the job. Nothing is submitted and nothing is spent. A device is chosen only when exactness asks for measured or any.", + "inputSchema": route_schema(json!({})), + }), + json!({ + "name": "run_routed", + "title": "Run a job on the route its contract chooses (can spend the person's money)", + "description": "Runs a job on the route plan_routes chooses: a method on this machine, or one of the person's own providers. THIS CAN SPEND THE PERSON'S MONEY OR QUOTA, when the contract allows a provider and one is chosen. A cost ceiling confirms nothing: a run that is not free is refused unless confirm is the word plan_routes gave for that route, its estimate and its program (its confirm.token), set only after the person has seen them and agreed to that run; if the route or its estimate changed since, it is refused with the new word. The answer is a job in the service's form, its result carrying the planner's reasoning under planner; a provider's result also carries a classical method's counts and their distance under shadow, or why no classical method could reach them. If the job has not finished within this call the answer has status running and an id, and get_provider_job collects it later. Do not run it again to find out: that is a second job, and it can be a second bill.", + "inputSchema": route_schema(json!({ "confirm": { "type": "string", "description": "The word plan_routes gave (confirm.token) for the route, the estimate and the program the person agreed to. A run that is not free is refused without it, whatever the contract's ceiling, and refused if what is chosen now is not what that word names." } })), + }), json!({ "name": "get_provider_job", "title": "Ask after a job on a provider", @@ -670,6 +795,27 @@ pub fn mcp_tools() -> Vec { ] } +/// What a routed job takes: a job's own members, under a contract that names no +/// provider. +fn route_schema(extra: Value) -> Value { + let mut s = json!({ + "type": "object", + "required": ["qasm", "contract"], + "properties": { + "qasm": { "type": "string", "description": "The program, OpenQASM 3. A provider takes one whose measurements all come at the end and whose every angle is a dyadic multiple of 2π; one it cannot take is a route with why." }, + "inputs": { "type": "object", "additionalProperties": { "type": "integer" }, "description": "A generator's inputs' values, as {\"n\": 5}." }, + "shots": { "type": "integer", "minimum": 1, "description": "Shots (default 1024)." }, + "seed": { "type": "integer", "minimum": 0, "description": "A seed." }, + "observables": { "type": "array", "items": { "type": "string" }, "description": "Pauli observables: a provider's job answers counts, so a method here answers these." }, + "contract": wai_quantum::engine::planner::contract_schema(), + } + }); + if let (Some(p), Some(e)) = (s["properties"].as_object_mut(), extra.as_object()) { + p.extend(e.clone()); + } + s +} + /// Appends these tools to a tools list. pub fn add_tools(tools: &mut Value) { if let Some(a) = tools.as_array_mut() { @@ -688,7 +834,7 @@ fn mcp_request(args: &Value) -> Result<(String, Value), String> { Some(_) => return Err("give \"inputs\" as an object of whole numbers".into()), }; let mut req = json!({ "qasm": crate::at_inputs(qasm.to_string(), &inputs)?, "provider": name }); - for k in ["shots", "seed"] { + for k in ["shots", "seed", "contract"] { if let Some(v) = args.get(k).filter(|v| !v.is_null()) { req[k] = v.clone(); } @@ -696,6 +842,27 @@ fn mcp_request(args: &Value) -> Result<(String, Value), String> { Ok((name, req)) } +/// The request a routed call makes: the program read at its inputs, under its +/// contract, naming no provider. +fn mcp_routed(args: &Value) -> Result { + let qasm = args.get("qasm").and_then(Value::as_str).ok_or("give \"qasm\": the program")?; + if args.get("contract").is_none_or(Value::is_null) { + return Err("give \"contract\": what the job wants; it is the contract that weighs the routes".into()); + } + let inputs: wai_quantum::qasm::Inputs = match args.get("inputs") { + None | Some(Value::Null) => Default::default(), + Some(Value::Object(m)) => m.iter().map(|(k, v)| v.as_i64().map(|n| (k.clone(), n)).ok_or(format!("inputs: {k} takes a whole number"))).collect::>()?, + Some(_) => return Err("give \"inputs\" as an object of whole numbers".into()), + }; + let mut req = json!({ "qasm": crate::at_inputs(qasm.to_string(), &inputs)? }); + for k in ["shots", "seed", "observables", "contract"] { + if let Some(v) = args.get(k).filter(|v| !v.is_null()) { + req[k] = v.clone(); + } + } + Ok(req) +} + /// One of the tools, with `reg`, `stores` and `ledger`; `None` for another tool. pub fn mcp_call_with(name: &str, args: &Value, key: &SigningKey, reg: &Registry, stores: &Stores, ledger: &Ledger, wait: Wait) -> Option> { Some(match name { @@ -719,6 +886,25 @@ pub fn mcp_call_with(name: &str, args: &Value, key: &SigningKey, reg: &Registry, Err(e) => Err(e.to_string()), } })(), + "plan_routes" | "run_routed" => (|| { + let req = mcp_routed(args)?; + let (open, closed) = targets(reg, stores, crate::DEFAULT_MEMORY_GB << 30); + let book = crate::estimates::Book::for_job(&req, crate::estimates::Surface::Embedded); + let routed = pjob::route_with(&open, closed, &req, crate::DEFAULT_MEMORY_GB << 30, Some(&|p: &wai_quantum::engine::catalog::Plan| book.held(p))).map_err(|e| e.to_string())?.counted(ledger); + if name == "plan_routes" { + return Ok(routed.json()); + } + let Some(chosen) = routed.provider() else { + return pjob::run_routed_here(&routed, &req, key, json!({ "unmetered": crate::UNMETERED })).map_err(|e| e.to_string()); + }; + let t = open.iter().find(|t| t.name == chosen).ok_or("internal: the planner chose a provider it was not given")?; + let confirm = args.get("confirm").and_then(Value::as_str); + match pjob::start_routed(t, &routed, &req, confirm, ledger).and_then(|mut ticket| pjob::follow(t, &mut ticket, key, ledger, wait, std::thread::sleep)) { + Ok(progress) => Ok(progress.job().clone()), + Err(JobError::Unconfirmed { plan, message }) => Err(format!("refused: {message}. Show the person this route and its estimate; call again with confirm set to that word only when they agree to this run. The plan: {plan}")), + Err(e) => Err(e.to_string()), + } + })(), "get_provider_job" | "cancel_provider_job" => (|| { let handle = args.get("id").and_then(Value::as_str).ok_or("give \"id\": the job's id, from run_on_provider or list_provider_jobs")?; let _held = asking(); @@ -738,7 +924,7 @@ pub fn mcp_call_with(name: &str, args: &Value, key: &SigningKey, reg: &Registry, /// One of the tools, with the person's own registry and records; `None` for /// another tool. pub fn mcp_call(name: &str, args: &Value, key: &SigningKey) -> Option> { - if !matches!(name, "providers_list" | "provider_estimate" | "run_on_provider" | "get_provider_job" | "cancel_provider_job" | "list_provider_jobs") { + if !matches!(name, "providers_list" | "provider_estimate" | "plan_routes" | "run_routed" | "run_on_provider" | "get_provider_job" | "cancel_provider_job" | "list_provider_jobs") { return None; } match Books::load() { @@ -779,11 +965,22 @@ mod tests { fn the_tools_say_what_they_cost_and_run_on_provider_says_it_spends_money() { let t = mcp_tools(); let names: Vec<&str> = t.iter().map(|x| x["name"].as_str().unwrap()).collect(); - assert_eq!(names, ["providers_list", "provider_estimate", "run_on_provider", "get_provider_job", "cancel_provider_job", "list_provider_jobs"]); - let run = t[2]["description"].as_str().unwrap(); - assert!(run.contains("SPEND THE PERSON'S MONEY") && run.contains("confirm_cost"), "{run}"); - assert!(t[2]["inputSchema"]["properties"]["confirm_cost"].is_object()); - assert!(t[1]["description"].as_str().unwrap().contains("Nothing is submitted and nothing is spent")); + assert_eq!(names, ["providers_list", "provider_estimate", "run_on_provider", "plan_routes", "run_routed", "get_provider_job", "cancel_provider_job", "list_provider_jobs"]); + // Each tool that can send a job says it can spend, and takes the person's word: + // for a provider they name, that they agree; for a route the planner chose, + // the word for that route and its estimate, which no bare yes stands for. + for (i, word, kind) in [(2, "confirm_cost", "boolean"), (4, "confirm", "string")] { + let run = t[i]["description"].as_str().unwrap(); + assert!(run.contains("SPEND THE PERSON'S MONEY") && run.contains(word), "{run}"); + assert_eq!(t[i]["inputSchema"]["properties"][word]["type"], kind); + } + for i in [1, 3] { + assert!(t[i]["description"].as_str().unwrap().contains("Nothing is submitted and nothing is spent"), "{}", t[i]["name"]); + let props = &t[i]["inputSchema"]["properties"]; + assert!(props.get("confirm_cost").is_none() && props.get("confirm").is_none(), "{}", t[i]["name"]); + } + // A routed tool weighs a contract, and requires one. + assert_eq!(t[3]["inputSchema"]["required"], json!(["qasm", "contract"])); } /// The tools against the reference provider, in this process. diff --git a/wai/wai-quantum-cli/tests/estimates.rs b/wai/wai-quantum-cli/tests/estimates.rs new file mode 100644 index 000000000..835791a26 --- /dev/null +++ b/wai/wai-quantum-cli/tests/estimates.rs @@ -0,0 +1,278 @@ +//! A contract's energy ceiling on the command line: held by a live reading while +//! the run goes, which stops it, on a route something can read and stop, and +//! refused with why on one nothing can. An estimate beside a route can refuse a +//! job clearly past a ceiling, and promises nothing. + +use serde_json::{Value, json}; +use std::io::{BufRead, BufReader, Write}; +use std::path::PathBuf; +use std::process::{Command, Output, Stdio}; + +const BELL: &str = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"; + +struct Home(PathBuf); + +impl Home { + fn new(name: &str) -> Home { + let dir = std::env::temp_dir().join(format!("wai-quantum-estimates-{name}-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + std::fs::write(dir.join("bell.qasm"), BELL).unwrap(); + Home(dir) + } + + fn timings(&self) -> PathBuf { + self.0.join("timings.json") + } + + fn cmd(&self) -> Command { + let mut c = Command::new(env!("CARGO_BIN_EXE_wai-quantum")); + c.current_dir(&self.0).env("HOME", &self.0).env("XDG_CONFIG_HOME", self.0.join("config")).env("WAI_QUANTUM_TIMINGS", self.timings()).env_remove("WAI_QUANTUM_KEY").env_remove("WAI_QUANTUM_PROVIDERS"); + c + } + + fn run(&self, args: &[&str]) -> Output { + self.cmd().args(args).output().unwrap() + } +} + +impl Drop for Home { + fn drop(&mut self) { + let _ = std::fs::remove_dir_all(&self.0); + } +} + +fn route<'a>(planner: &'a Value, name: &str) -> &'a Value { + planner["routes"].as_array().unwrap().iter().find(|r| r["route"] == name).unwrap_or_else(|| panic!("no {name}: {planner}")) +} + +/// Whether a live reading can hold a ceiling on this host: a run under one says. +fn reads_here(h: &Home) -> bool { + let out = h.run(&["plan", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "1000", "--json"]); + let plan: Value = serde_json::from_slice(&out.stdout).unwrap_or(Value::Null); + plan["planner"]["routes"].as_array().is_some_and(|r| r.iter().any(|r| r["price"]["energy"]["watch"].is_string())) +} + +const BUSY: &str = "OPENQASM 3.0;\nqubit[24] q;\nbit[24] c;\nrx(0.3) q[0];\nc = measure q;\n"; + +/// A ceiling is held by a live reading of the run's own process: under it a job +/// runs and its whole figure is sealed; at it the process is killed, with no answer +/// and a receipt that says so and what the run took in all, and the command exits 4. +#[test] +fn a_run_is_stopped_at_its_ceiling_by_a_live_reading_and_its_receipt_says_so() { + let h = Home::new("ceiling"); + if !reads_here(&h) { + if cfg!(target_os = "macos") { + panic!("a Mac reads its own process's energy, so this test may not pass by skipping"); + } + println!("nothing reads a run on this host: a route is refused under a ceiling, as the next test holds"); + return; + } + let out = h.run(&["run", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "1000", "--demo-key", "--json"]); + assert_eq!(out.status.code(), Some(0), "{}", String::from_utf8_lossy(&out.stderr)); + let body: Value = serde_json::from_slice(&out.stdout).unwrap(); + let p = &body["result"]["planner"]; + assert!(route(p, "method:stabilizer")["price"]["energy"]["watch"].as_str().unwrap().contains("read about every"), "{p}"); + let whole = body["result"]["energy"]["joules_micro"].as_u64().map(|u| u as f64 / 1e6); + assert!(whole.is_some(), "a run under a ceiling is read whole: {}", body["result"]["energy"]); + assert_eq!(p["kept"]["energy"]["kept"], true, "{}", p["kept"]); + // A job that takes seconds, under a ceiling it reaches at once. + std::fs::write(h.0.join("busy.qasm"), BUSY).unwrap(); + let began = std::time::Instant::now(); + let out = h.run(&["run", "busy.qasm", "--method", "statevector", "--shots", "1000000", "--max-joules", "0.01", "--demo-key", "--json"]); + assert_eq!(out.status.code(), Some(4), "{}", String::from_utf8_lossy(&out.stderr)); + assert!(began.elapsed() < std::time::Duration::from_secs(60)); + let said = String::from_utf8_lossy(&out.stderr); + assert!(said.contains("stopped at its ceiling"), "{said}"); + let body: Value = serde_json::from_slice(&out.stdout).unwrap(); + let r = &body["result"]; + assert!(r["stopped"]["joules"].as_f64().unwrap() >= 0.01 && r["stopped"]["read"].as_str().unwrap().contains("the longest time between two reads") && r.get("counts").is_none(), "{r}"); + let whole = r["energy"]["joules_micro"].as_u64().map(|u| u as f64 / 1e6); + // What the killed run took in all is sealed, no less than what stopped it; where + // the kill left no honest whole reading (on Apple silicon a thread killed on a + // core loses its last stretch), the receipt says why instead. + assert!(whole.map_or(r["energy"]["unmetered"].is_string(), |w| w >= r["stopped"]["joules"].as_f64().unwrap()), "{}", r["energy"]); + assert_eq!((r["planner"]["kept"]["energy"]["kept"].as_bool(), r["accuracy"]["class"].as_str()), (Some(false), Some("none")), "{r}"); + std::fs::write(h.0.join("job.json"), body.to_string()).unwrap(); + let v = h.run(&["verify", "job.json", "--json"]); + assert_eq!(v.status.code(), Some(0), "{}", String::from_utf8_lossy(&v.stdout)); + let v = h.run(&["verify", "job.json", "--recheck", "--json"]); + assert_eq!(v.status.code(), Some(0), "a stopped run rechecks: {}", String::from_utf8_lossy(&v.stdout)); + // In words too, and the routed run is held the same way. + let out = h.run(&["run", "busy.qasm", "--method", "statevector", "--shots", "1000000", "--max-joules", "0.01", "--demo-key"]); + assert_eq!(out.status.code(), Some(4)); + assert!(String::from_utf8_lossy(&out.stdout).contains("stopped at its ceiling"), "{}", String::from_utf8_lossy(&out.stdout)); + let out = h.run(&["run", "busy.qasm", "--shots", "1000000", "--exactness", "any", "--allow-providers", "--max-joules", "0.01", "--demo-key", "--json"]); + assert_eq!(out.status.code(), Some(4), "{}", String::from_utf8_lossy(&out.stderr)); + assert!(serde_json::from_slice::(&out.stdout).unwrap()["result"]["stopped"].is_object()); + // A run that ends between two reads is read whole all the same: past its + // ceiling it is sealed as having missed it, and the command exits 4. + for _ in 0..3 { + let out = h.run(&["run", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "0.000001", "--demo-key", "--json"]); + let body: Value = serde_json::from_slice(&out.stdout).unwrap(); + let kept = &body["result"]["planner"]["kept"]["energy"]; + assert_eq!((out.status.code(), kept["kept"].as_bool()), (Some(4), Some(false)), "{kept} {}", body["result"]["energy"]); + } + // Read and kept, as what an estimate rests on. + let kept: Value = serde_json::from_str(&std::fs::read_to_string(h.timings()).unwrap()).unwrap(); + assert!(kept["machines"].as_object().unwrap().values().next().unwrap().as_object().is_some_and(|m| !m.is_empty()), "{kept}"); +} + +/// The run's process ends with the command line, however that ends: a SIGTERM or a +/// SIGKILL to it mid-run leaves nothing computing. One started with SIGCHLD ignored +/// still waits for its run. +#[test] +fn a_run_under_a_ceiling_ends_with_its_command_line() { + let h = Home::new("orphans"); + if !reads_here(&h) { + if cfg!(target_os = "macos") { + panic!("a Mac reads a process's own energy, so this test may not pass by skipping"); + } + return; + } + // A run that takes far longer than the window it is given to end in, within + // every cap: a long Clifford circuit on 3000 qubits, a million shots, by the + // stabilizer method (about 14 s on the Framework, measured). + let layer: String = std::iter::once("h q[0];\n".to_string()).chain((0..2999).map(|i| format!("cx q[{i}], q[{}];\n", i + 1))).collect(); + let long = format!("OPENQASM 3.0;\nqubit[3000] q;\nbit[3000] c;\n{}c = measure q;\n", layer.repeat(40)); + std::fs::write(h.0.join("busy.qasm"), long).unwrap(); + let alive = |pid: &str| Command::new("kill").args(["-0", pid]).stderr(Stdio::null()).status().is_ok_and(|s| s.success()); + for signal in ["-TERM", "-KILL"] { + let mut cli = h.cmd().args(["run", "busy.qasm", "--method", "stabilizer", "--shots", "1000000", "--max-joules", "1000000", "--demo-key"]).stdout(Stdio::null()).stderr(Stdio::null()).spawn().unwrap(); + let parent = cli.id().to_string(); + let child = (0..400) + .find_map(|_| { + let out = Command::new("pgrep").args(["-P", &parent]).output().ok()?; + let found = String::from_utf8_lossy(&out.stdout).split_whitespace().next().map(str::to_string); + if found.is_none() { + std::thread::sleep(std::time::Duration::from_millis(25)); + } + found + }) + .expect("the run's process started"); + // Given its job and working: killed before that, it would end for want of one. + std::thread::sleep(std::time::Duration::from_millis(500)); + assert!(alive(&child), "{signal}: the run ended before its command line was killed; it is meant to run long"); + assert!(Command::new("kill").args([signal, &parent]).status().unwrap().success()); + let _ = cli.wait(); + let gone = (0..80).any(|_| { + let still = alive(&child); + if still { + std::thread::sleep(std::time::Duration::from_millis(25)); + } + !still + }); + assert!(gone, "{signal}: the run's process {child} outlived its command line"); + } + // SIGCHLD ignored, as a parent can leave it (perl sets SIG_IGN and keeps it + // across the exec, where a shell's trap does not): the run is waited for. + let out = Command::new("perl") + .args(["-e", "$SIG{CHLD} = 'IGNORE'; exec @ARGV or die $!", env!("CARGO_BIN_EXE_wai-quantum")]) + .args(["run", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "1000", "--demo-key", "--json"]) + .current_dir(&h.0) + .env("HOME", &h.0) + .env("XDG_CONFIG_HOME", h.0.join("config")) + .env("WAI_QUANTUM_TIMINGS", h.timings()) + .output() + .unwrap(); + assert_eq!(out.status.code(), Some(0), "{}", String::from_utf8_lossy(&out.stderr)); +} + +/// Where nothing can stop a run the route is refused under a ceiling, with why: a +/// server's run, in a process with other work in it, on every tool that weighs a +/// route. `plan` shows what a run would be held by, and sends and runs nothing. +#[test] +fn a_route_nothing_can_stop_is_refused_under_a_ceiling_on_every_surface() { + let h = Home::new("surfaces"); + let mut child = h.cmd().args(["mcp", "--demo-key"]).stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::null()).spawn().unwrap(); + let mut stdin = child.stdin.take().unwrap(); + let mut stdout = BufReader::new(child.stdout.take().unwrap()); + let mut rpc = |id: u64, method: &str, params: Value| -> Value { + writeln!(stdin, "{}", json!({ "jsonrpc": "2.0", "id": id, "method": method, "params": params })).unwrap(); + stdin.flush().unwrap(); + let mut line = String::new(); + stdout.read_line(&mut line).unwrap(); + serde_json::from_str(&line).unwrap_or_else(|e| panic!("{e}: {line}")) + }; + rpc(1, "initialize", json!({ "protocolVersion": "2025-06-18" })); + let contract = json!({ "exactness": "exact", "max_joules": 1000, "providers": "allowed" }); + for (id, tool) in ["plan_quantum_circuit", "plan_routes", "run_routed", "run_quantum_circuit"].into_iter().enumerate() { + let r = rpc(id as u64 + 2, "tools/call", json!({ "name": tool, "arguments": { "qasm": BELL, "shots": 100, "contract": contract } })); + assert_eq!(r["result"]["isError"], true, "{tool}: {r}"); + let said = r["result"]["content"][0]["text"].as_str().unwrap(); + assert!(said.contains("[J071]") && said.contains("only a live reading holds a ceiling"), "{tool}: {said}"); + } + drop(stdin); + let _ = child.wait(); + assert!(!h.timings().exists(), "a server's runs are read by no one and kept nowhere"); + // The command line's plan says what a run here would be held by, or why nothing. + let out = h.run(&["plan", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "1000", "--allow-providers", "--json"]); + let planned: Value = serde_json::from_slice(&out.stdout).unwrap_or(Value::Null); + if reads_here(&h) { + assert_eq!(out.status.code(), Some(0), "{}", String::from_utf8_lossy(&out.stderr)); + assert!(route(&planned["planner"], "method:stabilizer")["price"]["energy"]["watch"].is_string(), "{planned}"); + let text = h.run(&["plan", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "1000"]); + assert!(String::from_utf8_lossy(&text.stdout).contains("held by a live reading"), "{}", String::from_utf8_lossy(&text.stdout)); + } else { + assert_eq!(out.status.code(), Some(1), "{planned}"); + assert!(String::from_utf8_lossy(&out.stderr).contains("[J071]"), "{}", String::from_utf8_lossy(&out.stderr)); + } +} + +/// The estimate beside a route is one: it can refuse a job clearly past a ceiling, +/// and promises nothing under it. Another machine's or build's runs are not its. +#[test] +fn an_estimate_refuses_a_job_clearly_past_a_ceiling_and_keeps_to_its_build() { + let h = Home::new("estimate"); + if !reads_here(&h) { + println!("nothing reads a run on this host"); + return; + } + let id = |v: &str| format!("{} {}-{} {} {v} {} ", wai_quantum::engine::energy::machine(), std::env::consts::OS, std::env::consts::ARCH, if cfg!(target_os = "macos") { "process" } else { "packages" }, if cfg!(debug_assertions) { "debug" } else { "release" }); + let seeded = |key: String, build: &str| { + let mut machines = serde_json::Map::new(); + let one = json!({ "work": 1_000_000, "elapsed_ms": 100, "window_us": 100_000, "watts": 10.0, "partial": false }); + machines.insert(format!("{key}{build}"), json!({ "statevector": vec![one; 3] })); + std::fs::write(h.timings(), json!({ "schema": "wai.quantum.timings/1", "machines": machines }).to_string()).unwrap(); + }; + let build = if cfg!(feature = "metal") { "metal" } else { "" }; + seeded(id(env!("CARGO_PKG_VERSION")), build); + let big = "OPENQASM 3.0;\nqubit[20] q;\nbit[20] c;\nrx(0.3) q[0];\nc = measure q;\n"; + std::fs::write(h.0.join("big.qasm"), big).unwrap(); + let args = ["plan", "big.qasm", "--method", "statevector", "--shots", "100", "--max-joules", "0.000001", "--json"]; + let out = h.run(&args); + assert_eq!(out.status.code(), Some(1), "{}", String::from_utf8_lossy(&out.stdout)); + let said = String::from_utf8_lossy(&out.stderr); + assert!(said.contains("[J071]") && said.contains("an estimate of") && said.contains("past the ceiling"), "{said}"); + // The same runs under another version: not this build's, so no estimate refuses. + seeded(id("0.0.1"), build); + let out = h.run(&args); + assert_eq!(out.status.code(), Some(0), "{}", String::from_utf8_lossy(&out.stderr)); +} + +/// The command line as a namespace's first process (pid 1), as a container's +/// entrypoint runs it: its run under a ceiling is its child like any other, and runs. +#[cfg(target_os = "linux")] +#[test] +fn a_run_under_a_ceiling_runs_when_its_command_line_is_pid_1() { + let h = Home::new("pid1"); + let can = Command::new("unshare").args(["--user", "--pid", "--fork", "true"]).status(); + if !can.is_ok_and(|s| s.success()) || !reads_here(&h) { + println!("this host makes no user and pid namespace for this user, or reads no run"); + return; + } + let out = Command::new("unshare") + .args(["--user", "--pid", "--fork"]) + .arg(env!("CARGO_BIN_EXE_wai-quantum")) + .args(["run", "bell.qasm", "--shots", "100", "--exactness", "exact", "--max-joules", "1000", "--demo-key", "--json"]) + .current_dir(&h.0) + .env("HOME", &h.0) + .env("XDG_CONFIG_HOME", h.0.join("config")) + .env("WAI_QUANTUM_TIMINGS", h.timings()) + .output() + .unwrap(); + assert_eq!(out.status.code(), Some(0), "{}", String::from_utf8_lossy(&out.stderr)); + let body: Value = serde_json::from_slice(&out.stdout).unwrap(); + assert!(body["result"]["counts"].is_object(), "{body}"); +} + diff --git a/wai/wai-quantum-cli/tests/providers.rs b/wai/wai-quantum-cli/tests/providers.rs index e4cd391a3..73407f488 100644 --- a/wai/wai-quantum-cli/tests/providers.rs +++ b/wai/wai-quantum-cli/tests/providers.rs @@ -283,6 +283,158 @@ fn an_agent_lists_estimates_is_refused_and_runs_only_with_confirm_cost() { let _ = child.wait(); } +/// A person's contract, on the command line: run here with its reasoning in the +/// receipt, refused with every route's reason, weighed against their providers, +/// and sent to the one that meets it, with a classical method's counts beside its +/// own. +#[test] +fn a_contract_weighs_every_route_and_its_receipt_says_why() { + let h = Home::new("contract"); + add_process(&h, "free-lab", &[], false); + add_process(&h, "paid", &["--price", "0.25", "--currency", "EUR", "--per", "job"], false); + let p = h.program(); + let file = |name: &str, text: &str| { + let f = h.dir.join(name); + std::fs::write(&f, text).unwrap(); + f.display().to_string() + }; + // Here, with its reasoning sealed and checked. + let body: Value = serde_json::from_str(&h.ok(&["run", &p, "--shots", "100", "--exactness", "exact", "--deadline", "60", "--demo-key", "--json"], "")).unwrap(); + assert_eq!(body["result"]["planner"]["choice"], "method:stabilizer", "{}", body["result"]["planner"]); + let saved = file("here.json", &body.to_string()); + let checked: Value = serde_json::from_str(&h.ok(&["verify", &saved, "--json", "--recheck"], "")).unwrap(); + assert_eq!((checked["valid"].as_bool(), checked["recheck"]["holds"].as_bool(), checked["planner"]["choice"].as_str()), (Some(true), Some(true), Some("method:stabilizer")), "{checked}"); + let told = h.ok(&["verify", &saved, "--recheck"], ""); + assert!(told.contains("wanted exact") && told.contains("priced again the same"), "{told}"); + // The words a person reads name each route. + let plan = h.ok(&["plan", &p, "--shots", "100", "--exactness", "exact"], ""); + assert!(plan.contains("method:stabilizer") && plan.contains("method:mps") && plan.contains("rejected (class"), "{plan}"); + // Refused, with why; as data, with every route; nothing else runs. + let out = h.run(&["run", &p, "--exactness", "measured", "--demo-key"], ""); + assert_eq!(out.status.code(), Some(1)); + let said = String::from_utf8_lossy(&out.stderr); + assert!(said.contains("[J071]") && said.contains("method:stabilizer"), "{said}"); + let out = h.run(&["plan", &p, "--exactness", "measured", "--json"], ""); + assert_eq!(out.status.code(), Some(1)); + let v: Value = serde_json::from_slice(&out.stdout).unwrap(); + assert_eq!((v["refused"]["code"].as_str(), v["planner"]["choice"].as_str()), (Some("J071"), None), "{v}"); + // Weighed against the person's providers, for a class they can give; for one + // none can give, none is asked, since an estimate's request carries the program. + let routed = h.ok(&["plan", &p, "--shots", "100", "--exactness", "simulated", "--allow-providers"], ""); + assert!(routed.contains("provider:free-lab") && routed.contains("provider:paid"), "{routed}"); + let here = h.ok(&["plan", &p, "--shots", "100", "--exactness", "exact", "--allow-providers"], ""); + assert!(here.contains("method:stabilizer") && !here.contains("provider:"), "{here}"); + assert!(jobs(&h).is_empty(), "a plan sends nothing"); + let body: Value = serde_json::from_str(&h.ok(&["run", &p, "--shots", "100", "--exactness", "exact", "--allow-providers", "--demo-key", "--json"], "")).unwrap(); + assert_eq!(body["result"]["method"], "stabilizer"); + assert!(jobs(&h).is_empty(), "a method here chosen, nothing is sent"); + // A provider's simulator asked for by its class: the free one, and its shadow. + let body: Value = serde_json::from_str(&h.ok(&["run", &p, "--shots", "100", "--seed", "3", "--exactness", "simulated", "--allow-providers", "--max-cost", "1:EUR", "--demo-key", "--json"], "")).unwrap(); + assert_eq!(body["result"]["provider"]["name"], "free-lab", "{}", body["result"]["planner"]); + assert_eq!(body["result"]["shadow"]["ran"], true); + assert_eq!(body["result"]["shadow"]["route"], "method:exact"); + let saved = file("routed.json", &body.to_string()); + let checked: Value = serde_json::from_str(&h.ok(&["verify", &saved, "--json", "--recheck"], "")).unwrap(); + assert_eq!((checked["valid"].as_bool(), checked["recheck"]["shadow"]["same"].as_bool()), (Some(true), Some(true)), "{checked}"); + assert_eq!(jobs(&h).len(), 1); + // Named under a contract, a provider runs only where the contract allows one. + let out = h.run(&["run", &p, "--provider", "paid", "--max-cost", "1:EUR", "--yes", "--demo-key"], ""); + assert_eq!(out.status.code(), Some(1)); + assert!(String::from_utf8_lossy(&out.stderr).contains("[J070]"), "{}", String::from_utf8_lossy(&out.stderr)); + // Allowed and under a ceiling, a cost that is not free still takes the person's word. + let out = h.run(&["run", &p, "--provider", "paid", "--allow-providers", "--max-cost", "1:EUR", "--demo-key"], ""); + assert_eq!(out.status.code(), Some(3), "{}", String::from_utf8_lossy(&out.stderr)); + let out = h.run(&["run", &p, "--provider", "paid", "--allow-providers", "--max-cost", "0.1:EUR", "--yes", "--demo-key"], ""); + assert_eq!(out.status.code(), Some(1)); + assert!(String::from_utf8_lossy(&out.stderr).contains("above the ceiling")); + let told = h.ok(&["run", &p, "--provider", "paid", "--allow-providers", "--max-cost", "1:EUR", "--yes", "--demo-key"], ""); + assert!(told.contains("shadow") && told.contains("method:exact") && told.contains("kept cost: kept"), "{told}"); + // A route the planner chose is confirmed by the word its dry run gave, never by a bare yes. + let measured = ["run", &p, "--shots", "100", "--exactness", "simulated", "--allow-providers", "--max-cost", "1:EUR", "--demo-key"]; + let out = h.run(&measured.iter().copied().chain(["--yes"]).collect::>(), ""); + assert_eq!(out.status.code(), Some(1)); + assert!(String::from_utf8_lossy(&out.stderr).contains("--confirm WORD"), "{}", String::from_utf8_lossy(&out.stderr)); + // A device target's job, with the person's providers beside it and a deadline. + let target: Value = serde_json::from_str(&h.ok(&["run", &p, "--shots", "50", "--target", "synthetic-line-5", "--allow-providers", "--deadline", "60", "--demo-key", "--json"], "")).unwrap(); + assert_eq!(target["result"]["planner"]["wanted_from"], "named", "{}", target["result"]["planner"]); + let saved = file("target.json", &target.to_string()); + let checked: Value = serde_json::from_str(&h.ok(&["verify", &saved, "--json"], "")).unwrap(); + assert_eq!(checked["valid"], true, "{checked}"); +} + +/// The same for an agent: a contract's routes, and a run on the one it chooses, +/// refused until the person confirms a cost. +#[test] +fn an_agent_weighs_a_contract_and_runs_on_the_route_it_chooses() { + let h = Home::new("agent-contract"); + add_process(&h, "paid", &["--price", "0.25", "--currency", "EUR", "--per", "job"], false); + let mut child = h.cmd().args(["mcp", "--demo-key"]).stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::null()).spawn().unwrap(); + let mut stdin = child.stdin.take().unwrap(); + let mut stdout = BufReader::new(child.stdout.take().unwrap()); + rpc(&mut stdin, &mut stdout, 1, "initialize", json!({ "protocolVersion": "2025-06-18" })); + let call = |stdin: &mut std::process::ChildStdin, stdout: &mut BufReader, id: u64, name: &str, args: Value| rpc(stdin, stdout, id, "tools/call", json!({ "name": name, "arguments": args }))["result"].clone(); + let simulated = json!({ "exactness": "simulated", "providers": "allowed", "max_cost": { "amount": "1", "currency": "EUR" } }); + let routes = call(&mut stdin, &mut stdout, 2, "plan_routes", json!({ "qasm": BELL, "shots": 100, "contract": simulated })); + assert_eq!(routes["isError"], false, "{routes}"); + assert_eq!(routes["structuredContent"]["planner"]["choice"], "provider:paid", "{routes}"); + assert_eq!(routes["structuredContent"]["provider_plan"]["estimate"]["amount"], "0.25", "{routes}"); + let refused = call(&mut stdin, &mut stdout, 3, "run_routed", json!({ "qasm": BELL, "shots": 100, "contract": simulated })); + assert_eq!(refused["isError"], true, "{refused}"); + let word = routes["structuredContent"]["confirm"]["token"].as_str().unwrap().to_string(); + assert!(refused["content"][0]["text"].as_str().unwrap().contains(&word), "{refused}"); + // A bare yes, or a word for another route or estimate, is no confirmation. + for wrong in [json!(true), json!("0123456789abcdef")] { + let no = call(&mut stdin, &mut stdout, 11, "run_routed", json!({ "qasm": BELL, "shots": 100, "contract": simulated, "confirm": wrong, "confirm_cost": true })); + assert_eq!(no["isError"], true, "{no}"); + } + assert!(jobs(&h).is_empty(), "nothing was sent"); + let ran = call(&mut stdin, &mut stdout, 4, "run_routed", json!({ "qasm": BELL, "shots": 100, "contract": simulated, "confirm": word })); + assert_eq!(ran["isError"], false, "{ran}"); + let job = ran["structuredContent"].clone(); + assert_eq!((job["result"]["provider"]["name"].as_str(), job["result"]["shadow"]["ran"].as_bool()), (Some("paid"), Some(true)), "{job}"); + let checked = call(&mut stdin, &mut stdout, 5, "verify_quantum_result", json!({ "job": job, "recheck": true })); + assert_eq!((checked["structuredContent"]["valid"].as_bool(), checked["structuredContent"]["recheck"]["holds"].as_bool()), (Some(true), Some(true)), "{checked}"); + // The same job as its text, read as the protocol reads it, and run again all the same. + let as_text = call(&mut stdin, &mut stdout, 12, "verify_quantum_result", json!({ "job": job.to_string(), "recheck": true })); + assert_eq!((as_text["structuredContent"]["valid"].as_bool(), as_text["structuredContent"]["recheck"]["holds"].as_bool()), (Some(true), Some(true)), "{as_text}"); + // Under a contract its own tools meet: a method here, and no money. + let here = call(&mut stdin, &mut stdout, 6, "run_routed", json!({ "qasm": BELL, "shots": 100, "contract": { "exactness": "exact", "providers": "allowed" } })); + assert_eq!((here["isError"].as_bool(), here["structuredContent"]["result"]["method"].as_str()), (Some(false), Some("stabilizer")), "{here}"); + // No contract: nothing to weigh, and the tool says so. + let bare = call(&mut stdin, &mut stdout, 7, "plan_routes", json!({ "qasm": BELL })); + assert_eq!(bare["isError"], true, "{bare}"); + // The engine's own run tool runs a contract, on what is here, and reaches no provider. + let run = call(&mut stdin, &mut stdout, 8, "run_quantum_circuit", json!({ "qasm": BELL, "shots": 50, "contract": { "exactness": "exact", "providers": "allowed" } })); + assert_eq!((run["structuredContent"]["result"]["planner"]["host"]["providers"].as_array().map(Vec::len), run["isError"].as_bool()), (Some(0), Some(false)), "{run}"); + let no = call(&mut stdin, &mut stdout, 9, "run_quantum_circuit", json!({ "qasm": BELL, "contract": { "exactness": "simulated", "providers": "allowed" } })); + assert_eq!(no["isError"], true, "{no}"); + let plan = call(&mut stdin, &mut stdout, 10, "plan_quantum_circuit", json!({ "qasm": BELL, "contract": { "exactness": "exact" } })); + assert_eq!(plan["structuredContent"]["planner"]["choice"], "method:stabilizer", "{plan}"); + drop(stdin); + let _ = child.wait(); + // The same on the command line: its dry run gives the word, and only that word sends. + let p = h.dir.join("agent-bell.qasm"); + std::fs::write(&p, BELL).unwrap(); + let p = p.display().to_string(); + let routed = ["run", &p, "--shots", "100", "--exactness", "simulated", "--allow-providers", "--max-cost", "1:EUR", "--demo-key"]; + fn with<'a>(base: &[&'a str], more: &[&'a str]) -> Vec<&'a str> { + base.iter().chain(more).copied().collect() + } + // The agent's word sent its run, so the dry run gives the next run's. + let shown = h.ok(&with(&routed, &["--dry-run"]), ""); + let next = shown.split("--confirm ").nth(1).and_then(|s| s.split_whitespace().next()).unwrap_or_else(|| panic!("{shown}")).to_string(); + assert!(next != word && shown.contains("sent once before"), "{shown}"); + let sent = jobs(&h).len(); + for (given, says) in [(word.as_str(), "already sent"), ("0123456789abcdef", "not what was confirmed")] { + let out = h.run(&with(&routed, &["--confirm", given]), ""); + assert_eq!(out.status.code(), Some(3), "{}", String::from_utf8_lossy(&out.stderr)); + assert!(String::from_utf8_lossy(&out.stderr).contains(says), "{}", String::from_utf8_lossy(&out.stderr)); + } + assert_eq!(jobs(&h).len(), sent, "a spent word, or one for another route or estimate, sends nothing"); + let body: Value = serde_json::from_str(&h.ok(&with(&routed, &["--confirm", &next, "--json"]), "")).unwrap(); + assert_eq!((body["result"]["provider"]["name"].as_str(), body["result"]["cost"]["confirmed"].as_bool()), (Some("paid"), Some(true)), "{body}"); +} + fn jobs(h: &Home) -> Vec { let v: Value = serde_json::from_str(&h.ok(&["providers", "jobs", "--json"], "")).unwrap(); v["jobs"].as_array().unwrap().clone() diff --git a/wai/wai-quantum-qpu/src/cloud_tasks.rs b/wai/wai-quantum-qpu/src/cloud_tasks.rs index 84abf247f..7c215bb7e 100644 --- a/wai/wai-quantum-qpu/src/cloud_tasks.rs +++ b/wai/wai-quantum-qpu/src/cloud_tasks.rs @@ -692,6 +692,10 @@ impl Provider for CloudTasks { Ok((counts, JobInfo::default(), Stated::counts(source))) } + fn can_cancel(&self) -> bool { + true + } + fn cancel(&self, id: &str) -> Result<(), QpuError> { let region = self.region_of_task(id); let url = format!("{}/quantum-task/{}/cancel", self.base(region), encode(id)); diff --git a/wai/wai-quantum-qpu/src/job.rs b/wai/wai-quantum-qpu/src/job.rs index 5683d4aad..2927d1c2b 100644 --- a/wai/wai-quantum-qpu/src/job.rs +++ b/wai/wai-quantum-qpu/src/job.rs @@ -29,6 +29,15 @@ //! still no; [`cancel`] is only ever someone asking. Any process can come back //! to a ticket, and its result is the one [`run`] would have sealed. //! +//! A job with a `contract` (wai/extensions/quantum-providers.md section 8.7) is +//! weighed by the engine's planner ([`planner`]): what the provider's estimate +//! says and leaves out is brought to it as a quote, and it runs only if the +//! provider meets the contract. [`route`] weighs every provider the person has +//! against the engine's own methods. Its reasoning goes in the receipt, with a +//! classical method's counts beside the provider's wherever one can reach them. +//! A ceiling is no confirmation: a run that is not free still runs only on the +//! person's word for that run (section 7). +//! //! A credential never appears in what these return: every message is passed //! through [`crate::Secret::redact`] first. @@ -40,7 +49,9 @@ use serde_json::{Value, json}; use std::time::Duration; use wai_quantum::ed25519_dalek::SigningKey; use wai_quantum::engine::targets::{import, layout}; -use wai_quantum::engine::{catalog, provider, receipt}; +use wai_quantum::engine::registry::Registry; +use wai_quantum::engine::refusal::{self, tag}; +use wai_quantum::engine::{catalog, planner, provider, receipt}; use wai_quantum::quantum_fabric::sampling::Counts; use wai_quantum::quantum_toolchain::native::{NativeGate, NativeProgram}; @@ -56,13 +67,28 @@ pub struct Target { pub kind: Kind, pub provider: Box, secrets: Vec, + job_bytes: u64, + /// What the name stands for: where the provider is, and whose account. + identity: String, } +/// The memory a classical method may take here beside a provider's job, unless a +/// host says otherwise ([`Target::with_job_bytes`]). +pub const SHADOW_BYTES: u64 = 8 << 30; + impl Target { /// `provider` under the person's name for it, with the credential it was /// given (kept only to take out of messages). pub fn new(name: impl Into, kind: Kind, provider: Box, secret: Option) -> Target { - Target { name: name.into(), kind, provider, secrets: secret.into_iter().collect() } + Target { name: name.into(), kind, provider, secrets: secret.into_iter().collect(), job_bytes: SHADOW_BYTES, identity: String::new() } + } + + /// The same, with what its name stands for (its endpoint, its settings and + /// where its credential is kept): a word that confirms a run is the word for + /// this provider, and a name pointed elsewhere is not it. + pub fn with_identity(mut self, identity: impl Into) -> Target { + self.identity = identity.into(); + self } /// Takes these out of messages too: the parts of a credential that is @@ -72,6 +98,13 @@ impl Target { self } + /// The same, with the memory a contract job's local routes and its shadow + /// may take here. + pub fn with_job_bytes(mut self, job_bytes: u64) -> Target { + self.job_bytes = job_bytes; + self + } + /// `text` with the credential taken out. pub fn redact(&self, text: &str) -> String { self.secrets.iter().fold(text.to_string(), |text, s| s.redact(&text)) @@ -244,10 +277,19 @@ pub struct Plan { placement: Value, device: Device, details: Details, + execution: Option, estimate: Result, String>, /// The device's names for the program's qubits, where its client sends it /// under them. names: Option, + /// The planner's reasoning, for a job with a contract. + reasoning: Option, + /// What it costs, in words. + cost: String, + /// What the target's name stood for when this was planned. + identity: String, + /// Whether its client can stop a job it sent. + stoppable: bool, } impl Plan { @@ -255,10 +297,97 @@ impl Plan { pub fn confirmation(&self) -> String { self.json["confirm"].as_str().unwrap_or("").to_string() } + + /// What the provider's estimate says of this job, and what it leaves out, as + /// the planner weighs it. Nothing has been sent. + pub fn quote(&self, name: &str) -> planner::Quote { + let mut q = planner::Quote::new(name, self.device.name.clone(), self.device.provenance.label()); + q.approximate = self.details.describe.get("approximate") == Some(&Value::Bool(true)) && self.device.provenance.label() != "silicon"; + let (money, seconds) = match &self.estimate { + Ok(Some(e)) => { + let m = match (&e.cost, e.free) { + (_, true) => json!({ "free": true }), + (Some(c), false) => { + let mut m = json!({ "free": false, "amount": c.amount, "currency": c.currency }); + if let Some(u) = &e.unit { + m["unit"] = json!(u); + } + // The least it can come to: no ceiling is met by it. + if e.at_least { + m["at_least"] = json!(true); + } + m + } + (None, false) => json!({ "free": false, "unknown": "the provider's estimate states no amount" }), + }; + (m, e.seconds) + } + Ok(None) => match &self.details.billing { + Billing::Free => (json!({ "free": true }), None), + Billing::Priced { unit, price, currency } => (json!({ "free": false, "unknown": format!("the provider gives no estimate; it bills {price} {currency} a {unit}") }), None), + Billing::Unknown(why) => (json!({ "free": false, "unknown": why }), None), + }, + Err(why) => (json!({ "free": false, "unknown": format!("the provider's estimate failed: {why}") }), None), + }; + // What a price of this kind cannot say, each in words a verifier knows. + let free = money["free"] == true; + let mut left = Vec::new(); + if seconds.is_none() { + left.push("time"); + } + if !free && money["amount"].is_null() { + left.push("amount"); + } + left.push("energy"); + // A client that sets mitigation off, or a device that has none, leaves nothing here. + let mitigation = self.execution.as_ref().and_then(|e| e["mitigation"].as_str().map(str::to_string)); + if !matches!(mitigation.as_deref(), Some("off" | "none")) { + left.push("mitigation"); + } + left.push("decoder"); + if !self.stoppable { + left.push("cancel"); + } + if !free { + left.push("charged"); + } + q.money = money; + q.seconds = seconds; + q.leaves_out = left.into_iter().map(str::to_string).collect(); + let c = &self.json["plan"]["compile"]; + q.program = json!({ "shots": self.read.shots, "native_gates": c["native_gates"], "two_qubit_gates": c["two_qubit_gates"], "swaps": c["swaps"] }); + if let Some(x) = self.placement.get("expected_success").filter(|x| x.is_number()) { + q.program["expected_success"] = x.clone(); + } + q + } } fn plan_with(t: &Target, sampler: &QpuSampler<&dyn Provider>, request: &Value) -> Result { - let read = provider::read(request).map_err(|e| t.fail(e))?; + let mut p = priced(t, sampler, request)?; + // Under a contract, the planner weighs this provider, and nothing is sent + // unless it meets it. + if planner::has_contract(request) { + let host = planner::Host::new(t.job_bytes).with_quotes(vec![p.quote(&t.name)]); + let d = planner::decide(Registry::builtins(), request, &host).map_err(|e| t.fail(e))?; + if !matches!(d.choice, planner::Choice::Provider(_)) { + let chosen = d.reasoning["choice"].as_str().unwrap_or_default(); + return Err(JobError::Failed(format!("this job's contract is met here by {chosen}, not by {}: the planner chose the cheaper route, and nothing was sent", t.name))); + } + p.reason_held(request, d.reasoning, &t.name)?; + } + Ok(p) +} + +/// Under a contract a provider is asked nothing where the contract does not allow +/// one: not its description, and not an estimate, whose request carries the +/// program. This comes before any of them. +fn allowed(t: &Target, request: &Value) -> Result<(), JobError> { + planner::provider_allowed(request).map_err(|e| t.fail(e)) +} + +fn priced(t: &Target, sampler: &QpuSampler<&dyn Provider>, request: &Value) -> Result { + let read = provider::read_named(request, Some(&t.name)).map_err(|e| t.fail(e))?; if read.provider != t.name { return Err(JobError::Failed(format!("the job names the provider {:?}, and this is {:?}", read.provider, t.name))); } @@ -272,8 +401,8 @@ fn plan_with(t: &Target, sampler: &QpuSampler<&dyn Provider>, request: &Value) - Ok(None) => details.billing == Billing::Free, Err(_) => false, }; - let confirm = if free { - "free: it runs without a confirmation".to_string() + let cost = if free { + "free".to_string() } else { let cost = match &estimate { Ok(Some(Estimate { cost: Some(c), unit, at_least, .. })) => format!("the provider estimates {}{} {}{}", if *at_least { "at least " } else { "" }, c.amount, c.currency, unit.as_ref().map(|u| format!(", billed by the {u}")).unwrap_or_default()), @@ -283,8 +412,9 @@ fn plan_with(t: &Target, sampler: &QpuSampler<&dyn Provider>, request: &Value) - Billing::Free => "its cost is unknown".into(), }, }; - format!("not free: {cost}; it runs only when you confirm it (--yes on the command line, confirm_cost: true for an agent, the dialog in the desktop app)") + format!("not free: {cost}") }; + let confirm = if free { "free: it runs without a confirmation".to_string() } else { format!("{cost}; it runs only when you confirm it (--yes on the command line, confirm_cost: true for an agent, the dialog in the desktop app)") }; let json = json!({ "dry_run": true, "provider": provider_json(t, &device, &details), @@ -301,11 +431,263 @@ fn plan_with(t: &Target, sampler: &QpuSampler<&dyn Provider>, request: &Value) - "free": free, "confirm": confirm, }); - Ok(Plan { json, free, read, program, placement, device, details, estimate, names }) + let execution = t.provider.execution(&program); + Ok(Plan { json, free, read, program, placement, device, details, execution, estimate, names, reasoning: None, cost, identity: t.identity.clone(), stoppable: t.provider.can_cancel() }) +} + +impl Plan { + fn reason_with(&mut self, reasoning: Value) { + self.json["planner"] = reasoning.clone(); + self.reasoning = Some(reasoning); + } + + /// `reasoning` taken up for a run on `name`, once it is held to what a receipt + /// of it must be: a run whose receipt would be refused is not sent, and costs + /// nothing. Nothing else gives a plan that goes to a provider its reasoning. + fn reason_held(&mut self, request: &Value, reasoning: Value, name: &str) -> Result<(), JobError> { + planner::before_sending(request, &reasoning, name, self.read.shots).map_err(JobError::Failed)?; + self.reason_with(reasoning); + Ok(()) + } +} + +/// What the planner made of a contract job, with every provider brought. +pub struct Routed { + /// The reasoning: every route, each one's price or reason, and the choice. + pub reasoning: Value, + /// The route chosen, and its plan when it is one of the engine's methods. + pub choice: planner::Choice, + plans: Vec<(String, Plan)>, + /// The job's contract, which the word binds. + contract: Value, + /// How many runs of this job its word has sent before, as the ledger shows. + sent: usize, +} + +/// How many runs a ledger holds of a job whose word is `base`: each one recorded, +/// less those its provider refused before taking them, which were not sent. A run +/// the provider took is a run, whatever became of it after. +fn sends_of(ledger: &Ledger, base: &str) -> usize { + ledger.list().0.iter().filter(|t| t.confirms() == Some(base) && (t.state() != "failed" || t.provider_id().is_some())).count() +} + +/// The ledger held by this process alone while a word is counted and its run is +/// recorded, so that two sends of one word cannot both find it unspent. Held until +/// dropped; where no lock can be taken, nothing is sent. +struct WordLock(#[allow(dead_code)] std::fs::File); + +fn lock_words(ledger: &Ledger) -> Result { + let path = ledger.dir().join(".words.lock"); + let _ = std::fs::create_dir_all(ledger.dir()); + let file = std::fs::OpenOptions::new().create(true).truncate(false).write(true).open(&path).map_err(|e| JobError::Failed(format!("nothing was sent: the ledger's lock could not be opened ({e})")))?; + #[cfg(unix)] + { + use std::os::unix::io::AsRawFd; + unsafe extern "C" { + fn flock(fd: i32, operation: i32) -> i32; + } + /// `LOCK_EX` in ``. + const LOCK_EX: i32 = 2; + // SAFETY: the descriptor is this open file's, for the call. + if unsafe { flock(file.as_raw_fd(), LOCK_EX) } != 0 { + return Err(JobError::Failed(format!("nothing was sent: the ledger could not be locked ({})", std::io::Error::last_os_error()))); + } + } + Ok(WordLock(file)) +} + +impl Routed { + /// What a dry run shows: the reasoning, the local plan when a method was + /// chosen, and the provider's own plan when one was, with what a person + /// confirms it by when it is not free ([`Routed::confirmation`]). + pub fn json(&self) -> Value { + let mut v = json!({ "dry_run": true, "planner": self.reasoning }); + match &self.choice { + planner::Choice::Local(p) => v["plan"] = serde_json::to_value(p).unwrap_or(Value::Null), + planner::Choice::Provider(name) => { + if let Some((_, p)) = self.plans.iter().find(|(n, _)| n == name) { + v["provider_plan"] = p.json.clone(); + } + if let Some(token) = self.confirmation() { + let money = self.chosen_route()["price"]["money"].clone(); + v["confirm"] = json!({ + "token": token, + "route": format!("provider:{name}"), + "money": money, + "says": self.says(name, &token, self.sent), + }); + } + } + _ => {} + } + v + } + + /// What a person reads of a routed run that is not free: what it costs, and + /// the word, which is the one thing that confirms it. + fn says(&self, name: &str, token: &str, sent: usize) -> String { + let cost = self.plans.iter().find(|(n, _)| n == name).map(|(_, p)| p.cost.clone()).unwrap_or_default(); + let again = match sent { + 0 => String::new(), + 1 => " This job has been sent once before.".to_string(), + n => format!(" This job has been sent {n} times before."), + }; + format!("{cost}; a ceiling confirms nothing. It runs once, only on the person's word for this route, this device, this estimate, this program and this contract: --confirm {token} on the command line, confirm: \"{token}\" for an agent.{again}") + } + + fn chosen_route(&self) -> &Value { + let name = self.reasoning["choice"].as_str().unwrap_or(""); + self.reasoning["routes"].as_array().and_then(|a| a.iter().find(|r| r["route"] == name)).unwrap_or(&Value::Null) + } + + /// What a person confirms a routed run that is not free by: a digest of the + /// route chosen, who it is (its kind, device, provenance and description, and + /// what its name stands for), what its provider estimates it at (its amount, + /// currency and unit, or why that is not known) and the program and shots it + /// would send. A run is sent only with this word, made again at send time, so + /// a route, a device, an estimate or a program that changed since the person + /// saw it is not sent. `None` for a route that is free, or one of the + /// engine's methods. + pub fn confirmation(&self) -> Option { + self.word(self.sent) + } + + /// The word, taking the ledger's count of the runs of this job sent before: + /// a word confirms one run, so a dry run after one gives another word. + pub fn counted(mut self, ledger: &Ledger) -> Routed { + self.sent = self.base().map_or(0, |b| sends_of(ledger, &b)); + self + } + + fn said(&self) -> Option { + let planner::Choice::Provider(name) = &self.choice else { return None }; + let (_, p) = self.plans.iter().find(|(n, _)| n == name)?; + if p.free { + return None; + } + Some(json!({ + "route": format!("provider:{name}"), + "money": self.chosen_route()["price"]["money"], + "provider": p.json["provider"], + "identity": p.identity, + "program": compiled_json(&p.program)["program"], + "shots": p.read.shots, + "contract": self.contract, + })) + } + + fn base(&self) -> Option { + self.said().map(|s| blake3::hash(&receipt::canonical(&s)).to_hex()[..16].to_string()) + } + + fn word(&self, sent: usize) -> Option { + let mut said = self.said()?; + said["sent_before"] = json!(sent); + Some(blake3::hash(&receipt::canonical(&said)).to_hex()[..16].to_string()) + } + + /// The name of the provider chosen, when one was. + pub fn provider(&self) -> Option<&str> { + match &self.choice { + planner::Choice::Provider(n) => Some(n), + _ => None, + } + } +} + +/// `request`'s contract weighed against every provider in `targets` and the +/// engine's own methods, within `job_bytes` of memory: each provider is asked to +/// describe the device and estimate the job, and nothing is sent. A provider that +/// cannot run the job, or does not answer, is a route with why. The refusal, when +/// no route meets the contract, comes back with its reasons. +pub fn route(targets: &[Target], request: &Value, job_bytes: u64) -> Result { + route_with(targets, Vec::new(), request, job_bytes, None) +} + +/// [`route`], with `also` among the routes (the providers a host could not +/// open, each with why), and the host's word on a local route's energy, what it +/// estimates and what would read the run (engine::energy::Held). No provider is +/// asked anything, and none is listed, where the contract does not allow one or +/// wants a class no provider's counts are in: an estimate's request carries the +/// compiled program. +pub fn route_with(targets: &[Target], also: Vec, request: &Value, job_bytes: u64, joules: Option<&planner::Joules<'_>>) -> Result { + let contract = planner::Contract::read(request).map_err(JobError::Failed)?; + let asks_providers = contract.as_ref().is_some_and(|c| c.providers == Some(true) && c.exactness.as_deref().is_some_and(|w| matches!(w, "measured" | "simulated" | "any"))); + let (targets, also) = if asks_providers { (targets, also) } else { (&[][..], Vec::new()) }; + let mut quotes = also; + let mut plans = Vec::new(); + for t in targets { + let planned = QpuSampler::new(&*t.provider).map_err(|e| t.fail(e)).and_then(|sampler| priced(t, &sampler, request)); + match planned { + Ok(p) => { + quotes.push(p.quote(&t.name)); + plans.push((t.name.clone(), p)); + } + Err(e) => quotes.push(planner::Quote::cannot(t.name.clone(), e.to_string())), + } + } + let mut host = planner::Host::new(job_bytes).with_quotes(quotes); + if let Some(j) = joules { + host = host.with_joules(j); + } + let d = planner::decide(Registry::builtins(), request, &host).map_err(JobError::Failed)?; + if let planner::Choice::Provider(name) = &d.choice + && let Some((_, p)) = plans.iter_mut().find(|(n, _)| n == name) + { + p.reason_held(request, d.reasoning.clone(), name)?; + } + Ok(Routed { reasoning: d.reasoning, choice: d.choice, plans, contract: request.get("contract").cloned().unwrap_or(Value::Null), sent: 0 }) +} + +/// A local route the planner chose ([`route`]) run here, its result carrying the +/// reasoning and sealed with `key`: `energy` is the host's word on it. +pub fn run_routed_here(routed: &Routed, request: &Value, key: &SigningKey, energy: Value) -> Result { + let planner::Choice::Local(plan) = &routed.choice else { return Err(JobError::Failed("the planner chose a provider, and this runs what it chose here".into())) }; + let result = planner::run_chosen(Registry::builtins(), request, plan, &routed.reasoning).map_err(JobError::Failed)?; + let body = wai_quantum::engine::job::seal(request, plan, result, key, energy); + // A host gives no receipt its own verifier refuses. + let own = wai_quantum::engine::job::check(&body); + if !own.valid() { + return Err(JobError::Failed(format!("no receipt is given: this host's verifier would refuse it ({})", own.reasons.join(", ")))); + } + Ok(body) +} + +/// The provider [`route`] chose, as [`start`] sends it. One that is not free is +/// sent only when `confirm` is the word [`Routed::confirmation`] gives now: what +/// the person saw is what is sent, at the estimate they saw. Otherwise it is +/// refused, with the plan and the word that would confirm it. +pub fn start_routed(t: &Target, routed: &Routed, request: &Value, confirm: Option<&str>, ledger: &Ledger) -> Result { + let Some((_, p)) = routed.plans.iter().find(|(n, _)| *n == t.name) else { return Err(JobError::Failed(format!("the planner did not weigh {}", t.name))) }; + if routed.provider() != Some(t.name.as_str()) { + return Err(JobError::Failed(format!("the planner did not choose {}", t.name))); + } + let base = routed.base(); + // Counted, and the run recorded before it is sent, under one lock. + let _held = if base.is_some() { Some(lock_words(ledger)?) } else { None }; + let sent = base.as_deref().map_or(0, |b| sends_of(ledger, b)); + if let Some(token) = routed.word(sent) + && confirm != Some(token.as_str()) + { + let seen = match confirm { + Some(c) if (0..sent).any(|k| routed.word(k).as_deref() == Some(c)) => "that word confirmed a run of this job already sent, and a word confirms one run: the word below confirms another. ", + Some(_) => "the word given is not this route's at this estimate: what is chosen now, or what it costs, is not what was confirmed. ", + None => "", + }; + // The provider's plan, as a run on a provider named is refused with, saying + // what confirms this one. + let says = routed.says(&t.name, &token, sent); + let mut plan = p.json.clone(); + plan["confirm"] = json!(says); + plan["token"] = json!(token); + return Err(JobError::Unconfirmed { plan, message: format!("{seen}this run on {}: {says}", t.name) }); + } + start_planned(t, p, request, true, ledger, base.as_deref()) } /// The dry run: the plan for `request` on `t`, with nothing submitted. pub fn plan(t: &Target, request: &Value) -> Result { + allowed(t, request)?; let sampler = QpuSampler::new(&*t.provider).map_err(|e| t.fail(e))?; plan_with(t, &sampler, request) } @@ -335,20 +717,25 @@ fn sealing_of(t: &Target, p: &Plan, confirmed: bool) -> Value { let protocol = p.json["provider"]["protocol"].as_str().unwrap_or(PROTOCOL).to_string(); let mut compiled = named_compiled(&p.program, p.names.as_ref()); compiled["placement"] = p.placement.clone(); + let reasoning = p.reasoning.clone().unwrap_or(Value::Null); // A simulator the provider states is approximate (§5.1); a processor's // counts never are. let approximate = p.details.describe.get("approximate") == Some(&Value::Bool(true)) && p.device.provenance.label() != "silicon"; - json!({ + let mut sealing = json!({ "provider": provider_json(t, &p.device, &p.details), "calibration": p.details.calibration, "compiled": compiled, - "execution": t.provider.execution(&p.program), + "execution": p.execution, "approximate": approximate, "free": p.free, "estimate": estimate_json(&p.estimate), "confirmed": confirmed && !p.free, "why": format!("on {}, {} ({protocol}): compiled exactly to {} on its qubits and checked by simulation here before it was sent", t.name, p.device.name, basis_label(p.device.basis)), - }) + }); + if !reasoning.is_null() { + sealing["planner"] = reasoning; + } + sealing } /// The counts of job `id`, as a sealed job. Where its counts come from is the @@ -358,7 +745,7 @@ fn sealing_of(t: &Target, p: &Plan, confirmed: bool) -> Value { /// sent, else no one's (a job recorded before clients said, which the verifier /// takes on any kind: §8.4). #[allow(clippy::too_many_arguments)] -fn sealed(t: &Target, request: &Value, read: &provider::Request, sealing: &Value, id: &str, polls: u32, counts: Counts, info: &JobInfo, stated: &Stated, key: &SigningKey) -> Result { +fn sealed(t: &Target, request: &Value, read: &provider::Request, sealing: &Value, id: &str, polls: u32, counts: Counts, info: &JobInfo, stated: &Stated, elapsed_ms: Option, key: &SigningKey) -> Result { let charged = info.charged.as_ref().map(|c| json!({ "amount": c.amount, "currency": c.currency })); let measured = provider::Measured { counts, @@ -371,7 +758,11 @@ fn sealed(t: &Target, request: &Value, read: &provider::Request, sealing: &Value }; let execution = stated.execution.clone().or_else(|| sealing.get("execution").filter(|e| e.is_object()).cloned()).unwrap_or_else(provider::unstated_execution); let statement = provider::Statement::new(stated.counts_source.unwrap_or(CountsSource::VendorCounts), execution).approximate(sealing["approximate"] == true); - let result = provider::result_stated(read, measured, &statement).map_err(|e| t.fail(e))?; + let mut result = provider::result_stated(read, measured, &statement).map_err(|e| t.fail(e))?; + // A contract job's reasoning, its shadow and what it kept (section 8.7). + if let Some(reasoning) = sealing.get("planner") { + planner::seal_provider(Registry::builtins(), request, &mut result, reasoning, elapsed_ms).map_err(|e| t.fail(e))?; + } let body = provider::seal(request, result, key, sealing["why"].as_str().unwrap_or_default()); // A provider's word reaches the seal, and a host gives no receipt its own // verifier refuses, whatever a provider answered. @@ -388,13 +779,16 @@ fn sealed(t: &Target, request: &Value, read: &provider::Request, sealing: &Value /// within `wait` is cancelled, where the provider can cancel one: this keeps /// no record to come back to. [`start`] and [`follow`] keep one. pub fn run(t: &Target, request: &Value, confirmed: bool, key: &SigningKey, wait: Wait, sleep: impl Fn(Duration) + 'static) -> Result { + allowed(t, request)?; let sampler = QpuSampler::new(&*t.provider).map_err(|e| t.fail(e))?.with_wait(wait, sleep); let p = plan_with(t, &sampler, request)?; refuse_unconfirmed(t, &p, confirmed)?; let sealing = sealing_of(t, &p, confirmed); + let began = std::time::Instant::now(); let (counts, record, stated): (_, JobRecord, _) = sampler.run_compiled_stated(&p.read.circuit, &p.program, p.read.shots, p.read.seed).map_err(|e| t.fail(e))?; let info = JobInfo { service_kwh: record.service_kwh, calibration: record.calibration, charged: record.charged }; - sealed(t, request, &p.read, &sealing, &record.id, record.polls, counts, &info, &stated, key) + let elapsed = u64::try_from(began.elapsed().as_millis()).ok(); + sealed(t, request, &p.read, &sealing, &record.id, record.polls, counts, &info, &stated, elapsed, key) } /// What came of asking after a recorded job. Each holds the job in the form @@ -437,10 +831,18 @@ pub fn progress_of(ticket: &Ticket) -> Progress { /// that did not complete may have reached the provider, so it is `unknown`, /// and is not sent again: that could be a second bill. pub fn start(t: &Target, request: &Value, confirmed: bool, ledger: &Ledger) -> Result { + allowed(t, request)?; let sampler = QpuSampler::new(&*t.provider).map_err(|e| t.fail(e))?; let p = plan_with(t, &sampler, request)?; - refuse_unconfirmed(t, &p, confirmed)?; - let mut ticket = Ticket::recording(&t.name, request, &p.program, p.read.shots, p.read.seed, sealing_of(t, &p, confirmed), p.names.as_ref()); + start_planned(t, &p, request, confirmed, ledger, None) +} + +fn start_planned(t: &Target, p: &Plan, request: &Value, confirmed: bool, ledger: &Ledger, confirms: Option<&str>) -> Result { + refuse_unconfirmed(t, p, confirmed)?; + let mut ticket = Ticket::recording(&t.name, request, &p.program, p.read.shots, p.read.seed, sealing_of(t, p, confirmed), p.names.as_ref()); + if let Some(base) = confirms { + ticket.confirming(base); + } ledger.put(&ticket).map_err(|e| JobError::Failed(format!("nothing was sent: the job could not be recorded first ({e})")))?; match t.provider.submit_seeded(&p.program, p.read.shots, p.read.seed) { Ok(id) => { @@ -478,15 +880,39 @@ fn ask(t: &Target, ticket: &mut Ticket, key: &SigningKey, ledger: &Ledger) -> Re } let id = ticket.provider_id().ok_or_else(|| JobError::Failed(format!("the record of {} has no provider's id", ticket.handle())))?.to_string(); ticket.polled(); - match t.provider.status(&id) { + let mut status = t.provider.status(&id); + // A contract's deadline, from the job's submission: past it, the job is + // cancelled where this client can, and nothing is sealed (J074). One that + // finished first gives its result: it has been paid for. Only the provider's + // word ends the record: a cancel it has not finished, or a status that did + // not read, leaves the job to be asked after, since it can still finish and + // bill. A client that cannot cancel leaves it running, and it is reported so. + let late = matches!(status, Ok(JobStatus::Pending)) && planner::deadline_ms(ticket.request()).is_some_and(|d| ticket.elapsed_ms() as f64 > d); + if late { + match t.provider.cancel(&id) { + Ok(()) => status = t.provider.status(&id), + Err(QpuError::Unsupported(_)) => {} + Err(e) => return Err(t.fail(e)), + } + if let Ok(JobStatus::Ended { status: said, .. }) = &status + && said == "cancelled" + { + let d = planner::deadline_ms(ticket.request()).unwrap_or(0.0); + ticket.ended("cancelled", &t.redact(&tag(refusal::DEADLINE_PASSED, format!("cancelled at {}: it ran past its contract's deadline of {} s, and nothing was sealed", t.name, d / 1000.0)))); + ledger.put(ticket).map_err(|e| JobError::Failed(format!("the job was cancelled at its deadline, and that could not be recorded: {e}")))?; + return Ok(progress_of(ticket)); + } + } + match status { Ok(JobStatus::Pending) => return Ok(progress_of(ticket)), Ok(JobStatus::Done) => { - let read = provider::read(ticket.request()).map_err(|e| t.fail(e))?; + let read = provider::read_named(ticket.request(), Some(ticket.provider())).map_err(|e| t.fail(e))?; let program = ticket.program().map_err(|e| t.fail(e))?; let names = ticket.qubit_names().map_err(|e| t.fail(e))?; let (counts, info, stated) = t.provider.counts_stated(&id, &program, ticket.shots(), names.as_ref()).map_err(|e| t.fail(e))?; let sealing = sealing_from_record(ticket.sealing(), &program); - let body = sealed(t, ticket.request(), &read, &sealing, &id, ticket.polls(), counts, &info, &stated, key)?; + let elapsed = ticket.elapsed_ms(); + let body = sealed(t, ticket.request(), &read, &sealing, &id, ticket.polls(), counts, &info, &stated, Some(elapsed), key)?; ticket.done(body); } Ok(JobStatus::Ended { status, reason }) => { @@ -1034,6 +1460,490 @@ mod tests { assert_eq!(plain.json["plan"]["compile"]["layout"], json!([0, 1])); } + /// The reference, reading as the processor a contract may ask for. + fn silicon(r: &Arc) -> Target { + let r = Arc::clone(r); + let ch = Local(move |m: &Value| { + let mut a = r.handle(m, None); + if m["op"] == "describe" { + a["provenance"] = json!("silicon"); + a.as_object_mut().unwrap().remove("simulator"); + } + a + }); + Target::new("device", Kind::Process, Box::new(OpenProvider::new(ch)), None) + } + + fn priced_at(price: &str) -> Arc { + Arc::new(Reference::new(Config { price: Some((price.into(), "USD".into(), Per::Shot)), ..Config::default() }).unwrap()) + } + + /// A job's contract is weighed before anything is sent: one its provider + /// cannot meet is refused with why, and the provider was asked only to + /// estimate it. + #[test] + fn a_contract_is_weighed_before_anything_is_sent() { + let key = SigningKey::from_bytes(&[4; 32]); + let r = Arc::new(Reference::new(Config::default()).unwrap()); + let (t, ops, _) = watched(&r); + // A simulator is not a device, however free. + let e = run(&t, &json!({ "qasm": BELL, "provider": "lab", "shots": 100, "contract": { "providers": "allowed", "exactness": "measured" } }), false, &key, no_wait(), |_| {}).unwrap_err(); + assert!(e.to_string().ends_with("[J071]") && e.to_string().contains("simulated"), "{e}"); + assert_eq!(count(&ops, "submit"), 0); + // What it is, it meets. + let body = run(&t, &json!({ "qasm": BELL, "provider": "lab", "shots": 100, "seed": 3, "contract": { "providers": "allowed", "exactness": "simulated" } }), false, &key, no_wait(), |_| {}).unwrap(); + let c = wai_quantum::engine::job::check(&body); + assert!(c.valid(), "{:?}\n{}", c.reasons, body["result"]); + assert_eq!(count(&ops, "submit"), 1); + let p = &body["result"]["planner"]; + assert_eq!((p["choice"].as_str(), p["wanted"].as_str()), (Some("provider:lab"), Some("simulated")), "{p}"); + // A dry run shows it, and sends nothing. + let dry = plan(&t, &json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "allowed" } })).unwrap(); + assert_eq!(dry.json["planner"]["wanted_from"], "named"); + assert_eq!(dry.json["planner"]["shadow"]["route"], "method:exact", "{}", dry.json["planner"]); + assert_eq!(count(&ops, "submit"), 1); + // With no contract, none of it: its bytes are what they were. + let plain = run(&t, &json!({ "qasm": BELL, "provider": "lab", "shots": 100, "seed": 3 }), false, &key, no_wait(), |_| {}).unwrap(); + for k in ["planner", "shadow"] { + assert!(plain["result"].get(k).is_none(), "{k}"); + } + assert!(plan(&t, &json!({ "qasm": BELL, "provider": "lab" })).unwrap().json.get("planner").is_none()); + } + + /// The ceiling holds the estimate, and a ceiling is no confirmation: a run + /// that is not free still runs only on the person's word for it. + #[test] + fn a_cost_ceiling_holds_the_estimate_and_is_no_confirmation() { + let key = SigningKey::from_bytes(&[4; 32]); + let r = priced_at("0.0003"); + let (t, ops, _) = watched(&r); + let job = |most: &str| json!({ "qasm": BELL, "shots": 1000, "provider": "lab", "contract": { "providers": "allowed", "max_cost": { "amount": most, "currency": "USD" } } }); + // 1000 shots at 0.0003 is 0.3. + let e = run(&t, &job("0.29"), true, &key, no_wait(), |_| {}).unwrap_err(); + assert!(e.to_string().contains("above the ceiling") && e.to_string().ends_with("[J071]"), "{e}"); + assert_eq!(count(&ops, "submit"), 0); + assert!(matches!(run(&t, &job("0.3"), false, &key, no_wait(), |_| {}), Err(JobError::Unconfirmed { .. })), "a ceiling is no confirmation"); + assert_eq!(count(&ops, "submit"), 0); + let body = run(&t, &job("0.3"), true, &key, no_wait(), |_| {}).unwrap(); + assert!(wai_quantum::engine::job::check(&body).valid(), "{:?}", wai_quantum::engine::job::check(&body).reasons); + let kept = &body["result"]["planner"]["kept"]["cost"]; + assert_eq!((kept["kept"].as_bool(), kept["charged"]["amount"].as_str()), (Some(true), Some("0.3")), "{kept}"); + // What the price leaves out is said on its route. + let route = &body["result"]["planner"]["routes"].as_array().unwrap().iter().find(|r| r["route"] == "provider:lab").unwrap().clone(); + assert_eq!(route["price"]["money"]["amount"], "0.3"); + assert_eq!(route["price"]["time"]["basis"], "provider"); + assert_eq!(route["price"]["leaves_out"], json!(["energy", "mitigation", "decoder", "charged"]), "{route}"); + assert_eq!(route["price"]["program"]["shots"], 1000); + // Another currency is not this one, and an estimate that fails is unknown. + let e = run(&t, &json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "allowed", "max_cost": { "amount": "100", "currency": "EUR" } } }), true, &key, no_wait(), |_| {}).unwrap_err(); + assert!(e.to_string().contains("converts no currency"), "{e}"); + let quiet = Arc::new(Reference::new(Config::default()).unwrap()); + let ch = Local(move |m: &Value| if m["op"] == "estimate" { json!({ "ok": false, "error": { "code": "unsupported", "message": "no estimates" } }) } else if m["op"] == "describe" { let mut d = quiet.handle(m, None); d["billing"] = json!({}); d } else { quiet.handle(m, None) }); + let t = Target::new("lab", Kind::Process, Box::new(OpenProvider::new(ch)), None); + let e = plan(&t, &json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "allowed", "max_cost": { "amount": "100", "currency": "USD" } } })).err().unwrap(); + assert!(e.to_string().contains("does not meet a ceiling"), "{e}"); + } + + fn bench(names: &[(&str, Option<&str>)]) -> Vec { + names.iter().map(|(name, price)| { + let r = price.map_or_else(|| Arc::new(Reference::new(Config::default()).unwrap()), priced_at); + let mut t = silicon(&r); + t.name = (*name).into(); + t + }).collect() + } + + /// With every provider brought, the cheapest route that meets the contract + /// runs, and a local method that meets it costs nothing to send. + #[test] + fn every_provider_is_weighed_against_the_engine_s_own_methods() { + let key = SigningKey::from_bytes(&[4; 32]); + let r = Arc::new(Reference::new(Config::default()).unwrap()); + let (watching, ops, _) = watched(&r); + // The local route wins, and nothing is sent. + let routed = route(&[watching], &json!({ "qasm": BELL, "shots": 100, "contract": { "providers": "allowed", "exactness": "exact" } }), 1 << 30).unwrap(); + assert_eq!(routed.reasoning["choice"], "method:stabilizer", "{}", routed.reasoning); + assert_eq!(count(&ops, "submit"), 0); + assert!(routed.provider().is_none()); + let req = json!({ "qasm": BELL, "shots": 100, "contract": { "providers": "allowed", "exactness": "exact" } }); + let body = run_routed_here(&routed, &req, &key, json!({ "unmetered": "a test" })).unwrap(); + assert!(wai_quantum::engine::job::check(&body).valid(), "{:?}", wai_quantum::engine::job::check(&body).reasons); + // A contract that wants a class no provider's counts are in asks no + // provider anything: an estimate's request carries the program. + assert_eq!(body["result"]["planner"]["host"]["providers"], json!([])); + assert_eq!((count(&ops, "estimate"), count(&ops, "describe")), (0, 0), "{:?}", ops.lock().unwrap()); + let never = route(&[watched(&r).0], &json!({ "qasm": BELL, "shots": 100, "contract": { "exactness": "any" } }), 1 << 30).unwrap(); + assert_eq!(never.reasoning["host"]["providers"], json!([]), "providers: never asks none"); + // A device wanted: of three, the cheapest under the ceiling. + let records = Records::new("routed"); + let want = json!({ "qasm": BELL, "shots": 1000, "seed": 2, "contract": { "providers": "allowed", "exactness": "measured", "max_cost": { "amount": "0.5", "currency": "USD" } } }); + let targets = bench(&[("dear", Some("0.001")), ("cheap", Some("0.0002")), ("mid", Some("0.0004"))]); + let routed = route(&targets, &want, 1 << 30).unwrap(); + assert_eq!(routed.provider(), Some("cheap"), "{}", routed.reasoning); + let dear = routed.reasoning["routes"].as_array().unwrap().iter().find(|r| r["route"] == "provider:dear").unwrap(); + assert_eq!(dear["rejected"]["code"], "cost"); + assert_eq!(routed.json()["provider_plan"]["plan"]["method"], "provider"); + // Sent, and collected as any job is, by the provider the planner chose. + let t = targets.iter().find(|t| t.name == "cheap").unwrap(); + // Confirmed only by the word for this route, its estimate and its program. + let token = routed.confirmation().expect("not free"); + assert_eq!(routed.json()["confirm"]["token"], token.as_str()); + assert!(matches!(start_routed(t, &routed, &want, None, &records.ledger()), Err(JobError::Unconfirmed { .. }))); + assert!(matches!(start_routed(t, &routed, &want, Some("yes"), &records.ledger()), Err(JobError::Unconfirmed { .. })), "no bare word confirms"); + // Seen at one estimate, sent at another: refused, with the new word. + let dearer = bench(&[("dear", Some("0.001")), ("cheap", Some("0.0003")), ("mid", Some("0.0004"))]); + let rerouted = route(&dearer, &want, 1 << 30).unwrap(); + assert_eq!(rerouted.provider(), Some("cheap")); + let Err(JobError::Unconfirmed { message, .. }) = start_routed(dearer.iter().find(|t| t.name == "cheap").unwrap(), &rerouted, &want, Some(&token), &records.ledger()) else { panic!("a word for another estimate confirmed this one") }; + assert!(message.contains("not what was confirmed") && message.contains(&rerouted.confirmation().unwrap()), "{message}"); + assert!(start_routed(targets.iter().find(|t| t.name == "mid").unwrap(), &routed, &want, Some(&token), &records.ledger()).is_err(), "the planner chose another"); + let mut ticket = start_routed(t, &routed, &want, Some(&token), &records.ledger()).unwrap(); + let Progress::Done(body) = check(t, &mut ticket, &key, &records.ledger()).unwrap() else { panic!("not done") }; + let c = wai_quantum::engine::job::check(&body); + assert!(c.valid(), "{:?}\n{}", c.reasons, body["result"]); + assert!(body["request"].get("provider").is_none(), "the request is sealed as it was asked"); + assert_eq!(body["result"]["provider"]["name"], "cheap"); + assert_eq!(body["result"]["accuracy"]["class"], "measured"); + assert_eq!(body["result"]["shadow"]["ran"], true); + assert!(body["result"]["planner"]["kept"]["cost"]["kept"] == true, "{}", body["result"]["planner"]["kept"]); + // No device can be had for this, and none falls back to a simulator or a method. + let e = route(&targets, &json!({ "qasm": BELL, "shots": 1000, "contract": { "providers": "allowed", "exactness": "measured", "max_cost": { "amount": "0.01", "currency": "USD" } } }), 1 << 30).err().unwrap(); + assert!(e.to_string().ends_with("[J071]") && e.to_string().contains("above the ceiling"), "{e}"); + // One that cannot run it is a route with why, and the rest are still weighed. + let wide = "OPENQASM 3.0; qubit[6] q; bit[6] c; h q[0]; c = measure q;"; + let routed = route(&targets, &json!({ "qasm": wide, "shots": 10, "contract": { "providers": "allowed", "exactness": "any" } }), 1 << 30).unwrap(); + assert_eq!(routed.reasoning["routes"].as_array().unwrap().iter().find(|r| r["route"] == "provider:cheap").unwrap()["rejected"]["code"], "cannot", "{}", routed.reasoning); + assert_eq!(routed.reasoning["choice"], "method:stabilizer"); + } + + /// Under a contract that does not allow a provider, the one a job names is told + /// nothing: no description, and no estimate, whose request carries the program. + #[test] + fn a_provider_the_contract_does_not_allow_is_asked_nothing() { + let records = Records::new("not-allowed"); + let key = SigningKey::from_bytes(&[4; 32]); + let r = Arc::new(Reference::new(Config::default()).unwrap()); + let (t, ops, _) = watched(&r); + let req = json!({ "qasm": BELL, "shots": 100, "provider": "lab", "contract": { "exactness": "simulated" } }); + for refused in [plan(&t, &req).map(|_| ()).unwrap_err(), start(&t, &req, true, &records.ledger()).map(|_| ()).unwrap_err(), run(&t, &req, true, &key, no_wait(), |_| {}).map(|_| ()).unwrap_err()] { + assert!(refused.to_string().ends_with("[J070]"), "{refused}"); + } + assert!(ops.lock().unwrap().is_empty(), "{:?}", ops.lock().unwrap()); + // Allowed with no class named, a job keeps a classical class no provider's + // counts meet: none is asked for what could never be chosen. + // Named and allowed, under a class no provider's counts have: refused, and + // not described or asked for an estimate first. + let classical = json!({ "qasm": BELL, "shots": 100, "provider": "lab", "contract": { "providers": "allowed", "exactness": "exact" } }); + for refused in [plan(&t, &classical).map(|_| ()).unwrap_err(), start(&t, &classical, true, &records.ledger()).map(|_| ()).unwrap_err()] { + assert!(refused.to_string().ends_with("[J071]"), "{refused}"); + } + assert!(ops.lock().unwrap().is_empty(), "{:?}", ops.lock().unwrap()); + let routed = route(&[t], &json!({ "qasm": BELL, "shots": 100, "contract": { "providers": "allowed" } }), 1 << 30).unwrap(); + assert_eq!(routed.reasoning["host"]["providers"], json!([]), "{}", routed.reasoning); + assert!(ops.lock().unwrap().is_empty(), "{:?}", ops.lock().unwrap()); + } + + /// A reasoning no receipt could give is not taken up, so nothing goes out on it. + /// The planner gives none today: this holds the rule for the day one slips. + #[test] + fn a_reasoning_no_receipt_could_give_is_not_taken_up() { + let r = Arc::new(Reference::new(Config::default()).unwrap()); + let (t, _, _) = watched(&r); + let req = json!({ "qasm": BELL, "shots": 100, "provider": "lab", "contract": { "providers": "allowed", "exactness": "simulated" } }); + let mut p = plan(&t, &req).unwrap(); + let good = p.reasoning.clone().expect("a contract's plan is reasoned"); + let mut broken = good.clone(); + broken["shadow"]["class"] = json!("estimate"); + let refused = p.reason_held(&req, broken, "lab").unwrap_err(); + assert!(refused.to_string().contains("shadow"), "{refused}"); + assert_eq!(p.reasoning.as_ref(), Some(&good), "what was refused was not taken up"); + p.reason_held(&req, good, "lab").unwrap(); + } + + /// The word for a routed run names who it goes to, not only the name: another + /// device under the same name and price, or the name pointed at another + /// endpoint, is not what was confirmed. And what a person reads says what + /// confirms it, the word, and nothing that does not. + #[test] + fn the_word_for_a_routed_run_binds_the_provider_and_says_only_itself() { + let want = json!({ "qasm": BELL, "shots": 1000, "seed": 2, "contract": { "providers": "allowed", "exactness": "simulated", "max_cost": { "amount": "5", "currency": "USD" } } }); + let word = |t: Target| route(&[t], &want, 1 << 30).unwrap().confirmation().expect("not free"); + let priced = |device: &str| { + let r = Arc::new(Reference::new(Config { name: device.into(), price: Some(("0.001".into(), "USD".into(), Per::Shot)), ..Config::default() }).unwrap()); + Target::new("lab", Kind::Process, Box::new(OpenProvider::new(Local(move |m: &Value| r.handle(m, None)))), None) + }; + assert_eq!(word(priced("qpu-a")), word(priced("qpu-a"))); + assert_ne!(word(priced("qpu-a")), word(priced("qpu-b")), "another device under the name"); + assert_ne!(word(priced("qpu-a")), word(priced("qpu-a").with_identity("https://elsewhere")), "the name pointed elsewhere"); + let routed = route(&[priced("qpu-a")], &want, 1 << 30).unwrap(); + let says = routed.json()["confirm"]["says"].as_str().unwrap().to_string(); + assert!(says.contains(&routed.confirmation().unwrap()) && !says.contains("--yes") && !says.contains("confirm_cost"), "{says}"); + let records = Records::new("word"); + let t = priced("qpu-a"); + let Err(JobError::Unconfirmed { plan, message }) = start_routed(&t, &routed, &want, None, &records.ledger()) else { panic!("sent without a word") }; + assert!(!message.contains("--yes") && !message.contains("confirm_cost"), "{message}"); + assert!(plan["confirm"].is_string() && plan["token"] == routed.confirmation().unwrap().as_str(), "{plan}"); + } + + /// A word confirms one run: the same word does not send the job again, and a dry + /// run after it gives the word for another run. It binds the contract it was + /// given under: a deadline dropped is not what was confirmed. + #[test] + fn a_word_confirms_one_run_and_binds_its_contract() { + let r = Arc::new(Reference::new(Config { price: Some(("0.001".into(), "USD".into(), Per::Shot)), ..Config::default() }).unwrap()); + let (t, ops, _) = watched(&r); + let want = json!({ "qasm": BELL, "shots": 1000, "seed": 2, "contract": { "providers": "allowed", "exactness": "simulated", "max_cost": { "amount": "5", "currency": "USD" }, "deadline_seconds": 600 } }); + let records = Records::new("word-once"); + let ledger = records.ledger(); + let routed = || route(std::slice::from_ref(&t), &want, 1 << 30).unwrap(); + let word = routed().counted(&ledger).confirmation().expect("not free"); + start_routed(&t, &routed(), &want, Some(&word), &ledger).unwrap(); + assert_eq!(count(&ops, "submit"), 1); + let Err(JobError::Unconfirmed { plan, message }) = start_routed(&t, &routed(), &want, Some(&word), &ledger) else { panic!("one word sent a second run") }; + assert_eq!(count(&ops, "submit"), 1, "nothing more was sent"); + assert!(message.contains("already sent") && message.contains("sent once before"), "{message}"); + let next = routed().counted(&ledger).confirmation().unwrap(); + assert!(next != word && plan["token"] == next.as_str(), "{plan}"); + start_routed(&t, &routed(), &want, Some(&next), &ledger).unwrap(); + assert_eq!(count(&ops, "submit"), 2); + // Sent together, one word sends one run: the second waits for the first to + // be recorded, and finds the word spent. + let racing = Records::new("word-race"); + let word = routed().counted(&racing.ledger()).confirmation().unwrap(); + let go = std::sync::Barrier::new(4); + let sent: Vec = std::thread::scope(|s| { + let runs: Vec<_> = (0..4).map(|_| s.spawn(|| { + let ledger = racing.ledger(); + let (mine, _, _) = watched(&r); + let routed = route(std::slice::from_ref(&mine), &want, 1 << 30).unwrap(); + go.wait(); + start_routed(&mine, &routed, &want, Some(&word), &ledger).is_ok() + })).collect(); + runs.into_iter().map(|h| h.join().unwrap()).collect() + }); + assert_eq!(sent.iter().filter(|s| **s).count(), 1, "{sent:?}"); + // A run the provider took and then failed is a run: its word is spent. + let mut failed = racing.ledger().list().0.into_iter().find(|t| t.provider_id().is_some()).unwrap(); + failed.ended("failed", "the device failed it"); + racing.ledger().put(&failed).unwrap(); + assert!(matches!(start_routed(&t, &routed(), &want, Some(&word), &racing.ledger()), Err(JobError::Unconfirmed { .. }))); + // Under another contract the word is another. + let mut loose = want.clone(); + loose["contract"].as_object_mut().unwrap().remove("deadline_seconds"); + let elsewhere = Records::new("word-contract"); + let given = routed().counted(&elsewhere.ledger()).confirmation().unwrap(); + let other = route(std::slice::from_ref(&t), &loose, 1 << 30).unwrap(); + assert!(matches!(start_routed(&t, &other, &loose, Some(&given), &elsewhere.ledger()), Err(JobError::Unconfirmed { .. }))); + assert_eq!(count(&ops, "submit"), 2); + } + + /// An open-protocol provider says what its price leaves out: one whose describe + /// says it cannot cancel has `cancel` in its route's `leaves_out`, and an + /// estimate that is the least a job can come to meets no ceiling. + #[test] + fn an_open_provider_says_it_cannot_cancel_and_that_its_estimate_is_the_least() { + let r = Arc::new(Reference::new(Config { price: Some(("0.001".into(), "USD".into(), Per::Shot)), ..Config::default() }).unwrap()); + let edited = |edit: fn(&mut Value)| { + let r = Arc::clone(&r); + Target::new("lab", Kind::Process, Box::new(OpenProvider::new(Local(move |m: &Value| { + let mut a = r.handle(m, None); + edit(&mut a); + a + }))), None) + }; + let deadline = json!({ "qasm": BELL, "shots": 100, "contract": { "providers": "allowed", "exactness": "simulated", "deadline_seconds": 600, "max_cost": { "amount": "5", "currency": "USD" } } }); + let left = |t: Target| route(&[t], &deadline, 1 << 30).unwrap().reasoning["routes"].as_array().unwrap().iter().find(|x| x["route"] == "provider:lab").unwrap()["price"]["leaves_out"].clone(); + let cannot: fn(&mut Value) = |a| { + if a.get("protocol").is_some() { + a["cancels"] = json!(false); + } + }; + assert!(left(edited(cannot)).as_array().unwrap().contains(&json!("cancel"))); + assert!(!left(edited(|_| {})).as_array().unwrap().contains(&json!("cancel"))); + let least: fn(&mut Value) = |a| { + if a.get("amount").is_some() { + a["at_least"] = json!(true); + } + }; + let Err(refused) = route(&[edited(least)], &deadline, 1 << 30).map(|r| r.reasoning) else { panic!("an estimate that is the least met the ceiling") }; + let said = refused.to_string(); + assert!(said.contains("provider:lab: at least") && said.contains("the least it can come to"), "{said}"); + } + + /// Only the provider's word ends a job past its deadline. A cancel it has not + /// finished, or a status that does not read, leaves the job to be asked after, + /// and if it finishes it is sealed, saying the deadline was missed. A client + /// that cannot cancel leaves it running, says nothing failed, and its route says + /// so in what its price leaves out. + #[test] + fn a_job_past_its_deadline_ends_only_on_the_provider_s_word() { + let records = Records::new("cancelling"); + let key = SigningKey::from_bytes(&[4; 32]); + let req = json!({ "qasm": BELL, "shots": 100, "provider": "lab", "contract": { "providers": "allowed", "deadline_seconds": 0.01 } }); + // A cancel taken, the job still running at the provider, then done. + let r = Arc::new(Reference::new(Config { polls: 0, ..Config::default() }).unwrap()); + let holding = Arc::new(std::sync::atomic::AtomicBool::new(true)); + let cancels = Arc::new(std::sync::atomic::AtomicUsize::new(0)); + let scripted = |refuse_cancel: bool| { + let (r, holding, cancels) = (Arc::clone(&r), Arc::clone(&holding), Arc::clone(&cancels)); + Local(move |m: &Value| { + let held = holding.load(std::sync::atomic::Ordering::SeqCst); + match m["op"].as_str() { + Some("cancel") if refuse_cancel => json!({ "ok": false, "error": { "code": "unsupported", "message": "this device cannot" } }), + Some("cancel") => { + cancels.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + json!({ "ok": true }) + } + Some("status") if held => json!({ "ok": true, "status": "running" }), + Some("estimate") => { + let mut a = r.handle(m, None); + a["seconds"] = json!(0); + a + } + _ => r.handle(m, None), + } + }) + }; + for refuse_cancel in [false, true] { + holding.store(true, std::sync::atomic::Ordering::SeqCst); + let t = Target::new("lab", Kind::Process, Box::new(OpenProvider::new(scripted(refuse_cancel))), None); + let mut ticket = start(&t, &req, false, &records.ledger()).unwrap(); + std::thread::sleep(Duration::from_millis(30)); + let asked = check(&t, &mut ticket, &key, &records.ledger()).unwrap(); + assert!(matches!(asked, Progress::Waiting(_)), "{refuse_cancel}: {:?}", asked.job()); + assert!(ticket.waiting(), "the record stays open: the job can still finish and bill"); + holding.store(false, std::sync::atomic::Ordering::SeqCst); + let Progress::Done(body) = check(&t, &mut ticket, &key, &records.ledger()).unwrap() else { panic!("not collected") }; + assert_eq!(body["result"]["planner"]["kept"]["deadline"]["kept"], false, "{}", body["result"]["planner"]["kept"]); + assert!(wai_quantum::engine::job::check(&body).valid(), "{:?}", wai_quantum::engine::job::check(&body).reasons); + } + assert!(cancels.load(std::sync::atomic::Ordering::SeqCst) >= 1); + // A client with no cancel at all: said in the price, before anything is sent. + struct Uncancellable(Box); + impl Provider for Uncancellable { + fn device(&self) -> Result { + self.0.device() + } + fn details(&self) -> Result { + self.0.details() + } + fn submit(&self, program: &NativeProgram, shots: u64) -> Result { + self.0.submit(program, shots) + } + fn status(&self, id: &str) -> Result { + self.0.status(id) + } + fn counts(&self, id: &str, program: &NativeProgram, shots: u64) -> Result<(Counts, JobInfo), crate::QpuError> { + self.0.counts(id, program, shots) + } + } + let t = Target::new("lab", Kind::Process, Box::new(Uncancellable(target(Config::default()).provider)), None); + let p = plan(&t, &json!({ "qasm": BELL, "shots": 100, "provider": "lab", "contract": { "providers": "allowed" } })).unwrap(); + let routes = p.json["planner"]["routes"].as_array().unwrap().clone(); + let lab = routes.iter().find(|r| r["route"] == "provider:lab").unwrap(); + assert!(lab["price"]["leaves_out"].as_array().unwrap().iter().any(|w| w == "cancel"), "{lab}"); + } + + /// A job still at the provider past its contract's deadline is cancelled + /// there, since this host can, and nothing is sealed (J074); a job that + /// finished first is sealed all the same, saying it missed. + #[test] + fn a_job_past_its_deadline_is_cancelled_where_it_waits() { + let records = Records::new("deadline"); + let key = SigningKey::from_bytes(&[4; 32]); + let quick = |polls: u32| { + let r = Arc::new(Reference::new(Config { polls, ..Config::default() }).unwrap()); + let ops: Asked = Arc::new(std::sync::Mutex::new(Vec::new())); + let seen = Arc::clone(&ops); + let ch = Local(move |m: &Value| { + seen.lock().unwrap().push(m["op"].as_str().unwrap_or_default().to_string()); + let mut a = r.handle(m, None); + if m["op"] == "estimate" { + a["seconds"] = json!(0); + } + a + }); + (Target::new("lab", Kind::Process, Box::new(OpenProvider::new(ch)), None), ops) + }; + let req = json!({ "qasm": BELL, "shots": 100, "provider": "lab", "contract": { "providers": "allowed", "deadline_seconds": 0.01 } }); + let (t, ops) = quick(50); + let mut ticket = start(&t, &req, false, &records.ledger()).unwrap(); + std::thread::sleep(Duration::from_millis(30)); + let Progress::Ended(job) = check(&t, &mut ticket, &key, &records.ledger()).unwrap() else { panic!("not stopped at its deadline") }; + assert_eq!(count(&ops, "cancel"), 1, "{:?}", ops.lock().unwrap()); + assert!(job["status"] == "cancelled" && job["error"].as_str().unwrap().ends_with("[J074]") && job.get("result").is_none(), "{job}"); + // Done before anyone asked after its deadline: sealed, saying it missed. + let (t, ops) = quick(0); + let mut ticket = start(&t, &req, false, &records.ledger()).unwrap(); + std::thread::sleep(Duration::from_millis(30)); + let Progress::Done(body) = check(&t, &mut ticket, &key, &records.ledger()).unwrap() else { panic!("not sealed") }; + assert_eq!(count(&ops, "cancel"), 0); + assert_eq!(body["result"]["planner"]["kept"]["deadline"]["kept"], false, "{}", body["result"]["planner"]["kept"]); + assert!(wai_quantum::engine::job::check(&body).valid(), "{:?}", wai_quantum::engine::job::check(&body).reasons); + } + + /// A contract job's shadow is run where its counts are sealed, whichever + /// process comes back to it; and its reasoning was kept with its record. + #[test] + fn a_shadow_and_its_reasoning_outlive_what_sent_the_job() { + let records = Records::new("contract-record"); + let key = SigningKey::from_bytes(&[4; 32]); + let r = Arc::new(Reference::new(Config { polls: 2, ..Config::default() }).unwrap()); + let req = json!({ "qasm": BELL, "shots": 500, "seed": 7, "provider": "lab", "contract": { "providers": "allowed", "deadline_seconds": 3600 } }); + let handle = start(&on(&r), &req, false, &records.ledger()).unwrap().handle().to_string(); + let t = on(&r); + let mut back = records.ledger().get(&handle).unwrap(); + let Progress::Done(body) = follow(&t, &mut back, &key, &records.ledger(), no_wait(), |_| {}).unwrap() else { panic!("not done") }; + let c = wai_quantum::engine::job::check(&body); + assert!(c.valid(), "{:?}\n{}", c.reasons, body["result"]); + let res = &body["result"]; + assert_eq!((res["shadow"]["ran"].as_bool(), res["shadow"]["route"].as_str()), (Some(true), Some("method:exact"))); + assert_eq!(res["planner"]["kept"]["deadline"]["kept"], true); + assert!(res["planner"]["kept"]["deadline"]["elapsed_ms"].is_u64()); + let rc = wai_quantum::engine::planner::recheck(Registry::builtins(), &body).unwrap(); + assert_eq!(rc["holds"], true, "{rc}"); + // Asked again, the same job, and asks no one. + let mut again = records.ledger().get(&handle).unwrap(); + let Progress::Done(same) = check(&t, &mut again, &key, &records.ledger()).unwrap() else { panic!("not done") }; + assert_eq!(same, body); + } + + /// The reference's own estimate says no time for a deadline only when it gives + /// none; a shadow it leaves no time for says so. + #[test] + fn a_deadline_it_cannot_be_held_to_is_refused_and_one_that_leaves_no_time_says_so() { + let r = Arc::new(Reference::new(Config::default()).unwrap()); + let quiet = { + let r = Arc::clone(&r); + Local(move |m: &Value| { + let mut a = r.handle(m, None); + if m["op"] == "estimate" { + a.as_object_mut().unwrap().remove("seconds"); + } + a + }) + }; + let t = Target::new("lab", Kind::Process, Box::new(OpenProvider::new(quiet)), None); + let e = plan(&t, &json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "allowed", "deadline_seconds": 3600 } })).err().unwrap(); + assert!(e.to_string().contains("cannot be held to the deadline"), "{e}"); + let late = { + let r = Arc::clone(&r); + Local(move |m: &Value| { + let mut a = r.handle(m, None); + if m["op"] == "estimate" { + a["seconds"] = json!(100); + } + a + }) + }; + let t = Target::new("lab", Kind::Process, Box::new(OpenProvider::new(late)), None); + let key = SigningKey::from_bytes(&[4; 32]); + let body = run(&t, &json!({ "qasm": BELL, "provider": "lab", "shots": 100, "contract": { "providers": "allowed", "deadline_seconds": 100 } }), false, &key, no_wait(), |_| {}).unwrap(); + let s = &body["result"]["shadow"]; + assert_eq!((s["ran"].as_bool(), s["code"].as_str()), (Some(false), Some("budget")), "{s}"); + assert!(wai_quantum::engine::job::check(&body).valid(), "{:?}", wai_quantum::engine::job::check(&body).reasons); + } + #[test] fn the_free_listing_names_the_engine_the_service_and_free_providers_only() { let d = |b: Billing, tier: Option| Details { protocol: PROTOCOL.into(), calibration: None, billing: b, free_tier: tier, describe: json!({}) }; diff --git a/wai/wai-quantum-qpu/src/ledger.rs b/wai/wai-quantum-qpu/src/ledger.rs index 856dd9ca0..142c70634 100644 --- a/wai/wai-quantum-qpu/src/ledger.rs +++ b/wai/wai-quantum-qpu/src/ledger.rs @@ -190,6 +190,12 @@ impl Ticket { &self.value["request"] } + /// How long since the job was written down, in milliseconds: a contract's + /// deadline is held to it. + pub(crate) fn elapsed_ms(&self) -> u64 { + now_ms().saturating_sub(self.submitted_ms()) + } + pub(crate) fn sealing(&self) -> &Value { &self.value["sealing"] } @@ -207,6 +213,16 @@ impl Ticket { self.value["polls"].as_u64().unwrap_or(0) as u32 } + /// The word a routed run was confirmed by, less which run of it this is: the + /// same job confirmed again is told apart by how many were sent before. + pub(crate) fn confirms(&self) -> Option<&str> { + self.value["confirms"].as_str() + } + + pub(crate) fn confirming(&mut self, base: &str) { + self.value["confirms"] = json!(base); + } + pub(crate) fn polled(&mut self) { self.value["polls"] = json!(self.polls() + 1); } diff --git a/wai/wai-quantum-qpu/src/lib.rs b/wai/wai-quantum-qpu/src/lib.rs index 90bece0ef..70b47ab92 100644 --- a/wai/wai-quantum-qpu/src/lib.rs +++ b/wai/wai-quantum-qpu/src/lib.rs @@ -398,6 +398,12 @@ pub trait Provider { Err(QpuError::Unsupported("this client cannot cancel a job".into())) } + /// Whether this client can stop a job it sent: under a deadline, one that + /// cannot leaves a late job running, and the planner's price says so. + fn can_cancel(&self) -> bool { + false + } + /// What this client sets at the provider when it sends `program`, as /// a result's `execution` states it (§8.3), built from the very request it /// sends: its members, the settings among them, the five things a @@ -462,6 +468,10 @@ macro_rules! forward_provider { (**self).cancel(id) } + fn can_cancel(&self) -> bool { + (**self).can_cancel() + } + fn execution(&self, program: &NativeProgram) -> Option { (**self).execution(program) } diff --git a/wai/wai-quantum-qpu/src/open_provider.rs b/wai/wai-quantum-qpu/src/open_provider.rs index 8388a3060..b6085392b 100644 --- a/wai/wai-quantum-qpu/src/open_provider.rs +++ b/wai/wai-quantum-qpu/src/open_provider.rs @@ -420,7 +420,8 @@ pub fn estimate_of(a: &Value) -> Result { unit: a.get("unit").and_then(Value::as_str).map(String::from), seconds: a.get("seconds").and_then(Value::as_f64).filter(|s| s.is_finite() && *s >= 0.0), note: a.get("note").and_then(Value::as_str).map(|n| n.chars().take(400).collect()), - at_least: false, + // The least the job can come to, as a time-billed provider may only know (§5.2). + at_least: !free && a.get("at_least") == Some(&Value::Bool(true)), }) } @@ -706,6 +707,12 @@ impl Provider for OpenProvider { Ok((counts, info, Stated::counts(source).with_execution(execution))) } + /// What its `describe` says: a provider that cannot cancel says + /// `"cancels": false` (§5.1), and a price then says so. + fn can_cancel(&self) -> bool { + self.describe().map_or(true, |d| d.get("cancels") != Some(&Value::Bool(false))) + } + fn cancel(&self, id: &str) -> Result<(), QpuError> { match self.call("cancel", json!({ "job": id })) { Ok(_) => Ok(()), diff --git a/wai/wai-quantum-qpu/src/registry.rs b/wai/wai-quantum-qpu/src/registry.rs index e08c850f4..bb2de854f 100644 --- a/wai/wai-quantum-qpu/src/registry.rs +++ b/wai/wai-quantum-qpu/src/registry.rs @@ -772,7 +772,8 @@ pub fn open(entry: &Entry, stores: &Stores) -> Result { } Kind::Http | Kind::Process => (Box::new(OpenProvider::new(channel(entry, secret.clone())?).with_settings(entry.settings.clone())), secret), }; - Ok(Target::new(entry.name.clone(), entry.kind, provider, secret).with_secrets(parts)) + let identity = serde_json::json!({ "kind": entry.kind.name(), "endpoint": entry.endpoint, "command": entry.command, "settings": entry.settings, "credential": entry.credential.describe() }); + Ok(Target::new(entry.name.clone(), entry.kind, provider, secret).with_secrets(parts).with_identity(identity.to_string())) } #[cfg(test)] diff --git a/wai/wai-quantum-qpu/tests/clients.rs b/wai/wai-quantum-qpu/tests/clients.rs index fe62c25f1..fdc34a562 100644 --- a/wai/wai-quantum-qpu/tests/clients.rs +++ b/wai/wai-quantum-qpu/tests/clients.rs @@ -745,6 +745,78 @@ fn posted(requests: Vec) -> Value { body_json(requests.iter().rev().find(|r| r.method == Method::Post && !r.url.contains("iam.test")).expect("a submission")) } +/// A built-in kind under a contract, through a service that follows its own: the +/// provider's estimate is unknown, so a ceiling refuses it and naming it runs it; +/// its result carries the planner's reasoning and a classical method's counts +/// beside the device's, and keeps every rule of section 8.7. +#[test] +fn a_built_in_kind_runs_under_a_contract_and_a_classical_method_shadows_it() { + use wai_quantum::ed25519_dalek::SigningKey; + use wai_quantum_qpu::job::{self, JobError, Target}; + use wai_quantum_qpu::registry::Kind; + let target = || { + let service = PrxService { jobs: Mutex::new(HashMap::new()) }; + let t = kept(move |r: &Request| service.answer(r)); + Target::new("lab", Kind::PrxCircuits, Box::new(PrxCircuits::new(t, Secret::new("prx-token"), "test-qc").with_base("https://prx.test/api/v1")), None) + }; + let key = SigningKey::from_bytes(&[42; 32]); + let bell = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"; + let wait = Wait { interval: std::time::Duration::ZERO, polls: 10 }; + // Its client states no price: an unknown cost does not meet a ceiling. + let capped = json!({ "qasm": bell, "provider": "lab", "shots": 400, "contract": { "providers": "allowed", "max_cost": { "amount": "100", "currency": "USD" } } }); + let e = job::plan(&target(), &capped).err().unwrap().to_string(); + assert!(e.ends_with("[J071]") && e.contains("does not meet a ceiling"), "{e}"); + // Named, with the person's confirmation for an unknown cost, it runs. + let req = json!({ "qasm": bell, "provider": "lab", "shots": 400, "seed": 5, "contract": { "providers": "allowed", "exactness": "measured" } }); + assert!(matches!(job::run(&target(), &req, false, &key, wait, |_| {}), Err(JobError::Unconfirmed { .. }))); + let body = job::run(&target(), &req, true, &key, wait, |_| {}).unwrap(); + let c = wai_quantum::engine::job::check(&body); + assert!(c.valid(), "{:?}\n{}", c.reasons, body["result"]); + let r = &body["result"]; + assert_eq!((r["accuracy"]["class"].as_str(), r["planner"]["choice"].as_str()), (Some("measured"), Some("provider:lab"))); + let route = r["planner"]["routes"].as_array().unwrap().iter().find(|x| x["route"] == "provider:lab").unwrap(); + assert_eq!(route["price"]["leaves_out"], json!(["time", "amount", "energy", "mitigation", "decoder", "cancel", "charged"]), "{route}"); + assert!(route["price"]["money"]["unknown"].is_string(), "{route}"); + let s = &r["shadow"]; + assert_eq!((s["ran"].as_bool(), s["accuracy"]["class"].as_str()), (Some(true), Some("bit-exact")), "{s}"); + let total: u64 = s["counts"].as_object().unwrap().values().filter_map(Value::as_u64).sum(); + assert_eq!(total, 400); + // The service follows its contract and the circuit is a Bell pair: both answers + // are the same distribution, within what the shots leave. + let d = &s["distance"]; + assert!(d["total_variation"].as_f64().unwrap() < 0.15, "{d}"); + if let Some(dir) = std::env::var_os("WAI_QUANTUM_RECEIPT_CORPUS") { + std::fs::write(std::path::Path::new(&dir).join("scripted-contract-prx-circuits.json"), format!("{}\n", serde_json::to_string_pretty(&body).unwrap())).unwrap(); + } +} + +/// A price the service bills by the minute is estimated at the least a task can +/// come to: under a contract's ceiling it is not known to be within it, and the +/// route says so; named with no ceiling, its cost is the person's to confirm. +#[test] +fn a_cost_estimated_at_the_least_it_can_come_to_meets_no_ceiling() { + let target = || { + let service = TasksService::new(true, false); + let t = kept(move |r: &Request| service.answer(r)); + let keys = Keys::new("AKIDEXAMPLE", Secret::new("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"), None); + let client = CloudTasks::new(t, keys, "us-west-1", "arn:test:simulator", "bucket").unwrap().with_base("https://tasks.test"); + Target::new("tasks", Kind::CloudTasks, Box::new(client), None) + }; + let bell = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"; + let capped = json!({ "qasm": bell, "provider": "tasks", "shots": 100, "contract": { "providers": "allowed", "max_cost": { "amount": "100", "currency": "USD" } } }); + let e = job::plan(&target(), &capped).err().unwrap().to_string(); + assert!(e.ends_with("[J071]") && e.contains("the least it can come to"), "{e}"); + // Routed with every route in view, it is listed with its price and why. + let routed = json!({ "qasm": bell, "shots": 100, "contract": { "exactness": "simulated", "providers": "allowed", "max_cost": { "amount": "100", "currency": "USD" } } }); + let e = job::route(&[target()], &routed, 1 << 30).err().unwrap().to_string(); + assert!(e.ends_with("[J071]") && e.contains("provider:tasks: at least 0.003750 USD"), "{e}"); + // Named, with no ceiling: planned, its estimate shown, and its route met. + let named = json!({ "qasm": bell, "provider": "tasks", "shots": 100, "contract": { "providers": "allowed" } }); + let p = job::plan(&target(), &named).unwrap(); + let route = p.json["planner"]["routes"].as_array().unwrap().iter().find(|r| r["route"] == "provider:tasks").unwrap().clone(); + assert_eq!((route["outcome"].as_str(), route["price"]["money"]["at_least"].as_bool(), route["price"]["money"]["unit"].as_str()), (Some("chosen"), Some(true), Some("minute")), "{route}"); +} + /// Each built-in kind, through a service that follows its contract, states /// what its client sent (read from the very body it posts), where its counts /// come from, and its class by its device's provenance; and its receipt keeps diff --git a/wai/wai-quantum-service/README.md b/wai/wai-quantum-service/README.md index 561ee89a2..13b8347b1 100644 --- a/wai/wai-quantum-service/README.md +++ b/wai/wai-quantum-service/README.md @@ -102,6 +102,10 @@ How the methods run: - **stabilizer**, with noise, samples by Pauli frames against one noiseless outcome of the tableau, 64 shots to a machine word. Its counts have the law of independent noisy shots. Its expectation values are estimates with standard errors, from at least 10,000 shots unless `trajectories` sets the number. Amplitude damping is not a Pauli channel and is refused. - **trajectories** treats every shot as an independent noisy trajectory in law. Shots that took the same errors share one state, so the error-free part of a circuit, and the error-free majority of the shots, run once. `histories` in the result counts the distinct error histories that ran. +### Under a contract + +A job may carry a `contract`: the class wanted, a deadline, a cost ceiling, an energy ceiling, and whether a provider may be used ([section 8.7](../extensions/quantum-providers.md) of the provider protocol). The service prices each method here for it, rejects those that cannot meet it, runs the cheapest of the rest and seals its reasoning in the receipt. A job no method here meets is refused at once, and in a dry run, with every method's reason (`J071`). The service reaches no provider: none is among its routes, whatever the contract allows, and a contract that wants a device's counts is refused. A dry run's energy is an estimate from what it has metered, and it promises nothing. A `max_joules` is held by a live reading of the worker while it runs, about every ten milliseconds as the host schedules the service: at the ceiling the worker is killed, read whole before it is reaped where the host allows, and a receipt is sealed that says so, with no answer in it, the worker's whole figure and the longest time between two reads. A Mac whose counter reads nothing for a process (an Intel one) reads no worker, so its routes are refused under a ceiling. A route on a host or a device nothing here reads is refused under a ceiling (`energy_unwatched`), and an estimate clearly past the ceiling refuses a job before it runs (`energy`). A run past its contract's deadline is stopped (`J074`), and nothing is sealed. A queued job keeps the reasoning it was admitted with across a restart. A contract is one job's: a set refuses one (`J073`). + ### Programs that measure in the middle A program that measures a qubit and then acts on it, resets a qubit after its first gate, or uses `if` on measured bits runs on `statevector` or `stabilizer`. `auto` picks the stabilizer tableau when every gate is Clifford, and the state vector otherwise. diff --git a/wai/wai-quantum-service/schemas/service-tools.v1.json b/wai/wai-quantum-service/schemas/service-tools.v1.json index e06c0aa2e..00fe849dd 100644 --- a/wai/wai-quantum-service/schemas/service-tools.v1.json +++ b/wai/wai-quantum-service/schemas/service-tools.v1.json @@ -64,6 +64,10 @@ "type": "object", "description": "For a provider's result, what it says of itself." }, + "planner": { + "type": "object", + "description": "For a job under a contract, what its reasoning says: the route chosen, the class wanted and given, whether the choice depends on the host, what was kept, and the shadow." + }, "key": { "type": [ "string", @@ -452,6 +456,9 @@ } } } + }, + "planner": { + "$ref": "https://git.transaction.science/Transaction-Science/open-standards/raw/branch/main/wai/wai-quantum/schemas/job-result.v1.json#/$defs/planner" } } }, diff --git a/wai/wai-quantum-service/src/energy.rs b/wai/wai-quantum-service/src/energy.rs index 2dcdd5219..065f054df 100644 --- a/wai/wai-quantum-service/src/energy.rs +++ b/wai/wai-quantum-service/src/energy.rs @@ -57,7 +57,15 @@ pub fn meter() -> &'static Meter { if std::env::var("WAI_QSVC_ENERGY").is_ok_and(|v| v == "0") { Meter::Unmetered("the service was started with energy metering off (WAI_QSVC_ENERGY=0)".into()) } else if cfg!(target_os = "macos") { - Meter::Process + mac_meter(wai_quantum::engine::energy::own().is_some() || { + // A read of nothing is read again after a short spin: an idle process + // can read nothing on a live counter. + let until = std::time::Instant::now() + std::time::Duration::from_millis(20); + while std::time::Instant::now() < until { + std::hint::spin_loop(); + } + wai_quantum::engine::energy::own().is_some() + }) } else if cfg!(target_os = "linux") { match Packages::open() { Ok(p) => Meter::Packages(p), @@ -69,6 +77,16 @@ pub fn meter() -> &'static Meter { }) } +/// A Mac's meter, by whether this process's own counter reads: one that reads +/// nothing (an Intel Mac's) gives no live reading, so no route a `watch`. +fn mac_meter(reads: bool) -> Meter { + if reads { + Meter::Process + } else { + Meter::Unmetered("this Mac's CPU energy counter reads nothing for a process here".into()) + } +} + /// Whether child `pid` has exited, without reaping it: `Some(true)` once it /// has (it is then readable by [`read`] until reaped), `Some(false)` while it /// runs, `None` where this cannot be told (off macOS, or the wait failed), in @@ -101,13 +119,22 @@ pub fn exited_unreaped(_pid: u32) -> Option { None } -// The one test reads the kernel's counter, which only macOS has. -#[cfg(all(test, target_os = "macos"))] +#[cfg(test)] mod tests { use super::*; + /// A Mac whose counter reads nothing is no meter, so a contract's ceiling is + /// refused there rather than admitted and lost a second into the run. + #[test] + fn a_mac_whose_counter_reads_nothing_has_no_meter() { + assert!(matches!(mac_meter(false), Meter::Unmetered(_))); + assert!(matches!(mac_meter(true), Meter::Process)); + } + /// A child that burns CPU and exits reads a complete, non-zero count while /// it is unreaped, over a window that covers its run; once reaped, it is gone. + /// Only macOS's kernel has the counter. + #[cfg(target_os = "macos")] #[test] fn an_exited_worker_reads_its_whole_energy_before_it_is_reaped() { let mut child = std::process::Command::new("/bin/sh") diff --git a/wai/wai-quantum-service/src/http.rs b/wai/wai-quantum-service/src/http.rs index d69720d8b..080b97b69 100644 --- a/wai/wai-quantum-service/src/http.rs +++ b/wai/wai-quantum-service/src/http.rs @@ -99,7 +99,8 @@ use std::net::{IpAddr, SocketAddr}; use std::sync::Arc; use std::time::Duration; use wai_quantum::engine::refusal::{self, tag}; -use wai_quantum::engine::sets; +use wai_quantum::engine::registry::Registry; +use wai_quantum::engine::{planner, sets}; /// The largest request body, bytes. pub const MAX_BODY: usize = 1 << 20; @@ -286,6 +287,15 @@ pub(crate) fn plan_job(app: &App, request: &Value) -> Result<(catalog::Plan, Wor return Ok((sets::summary(&plans), Work::Set { items, plans })); } job_bounds(request)?; + // A contract is weighed against the methods here, and the service reaches no + // provider, so none is ever among its routes. + if planner::has_contract(request) { + let joules = |p: &catalog::Plan| app.service.figure(p); + let host = planner::Host::new(cap).with_joules(&joules); + let d = planner::decide(Registry::builtins(), request, &host).map_err(|e| (400, e))?; + let planner::Choice::Local(p) = d.choice else { return Err((500, "the planner chose a route this service does not have".to_string())) }; + return Ok((p, Work::Planned(d.reasoning))); + } Ok((catalog::plan(request, cap).map_err(|e| (400, e))?, Work::One)) } @@ -351,12 +361,23 @@ pub(crate) fn dry_run(app: &App, who: &str, request: &Value) -> Result { + Work::One | Work::Planned(_) => { let (t, e) = estimate(&plan); (t, e, None) } diff --git a/wai/wai-quantum-service/src/jobs.rs b/wai/wai-quantum-service/src/jobs.rs index 5fceb7394..7272ccd20 100644 --- a/wai/wai-quantum-service/src/jobs.rs +++ b/wai/wai-quantum-service/src/jobs.rs @@ -64,7 +64,7 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::sync::{Notify, Semaphore, broadcast}; use wai_quantum::engine::refusal::{self, tag}; -use wai_quantum::engine::{receipt as canon, sets}; +use wai_quantum::engine::{planner, receipt as canon, sets}; /// The service's limits, from the environment ([`Config::from_env`]). #[derive(Clone, Debug)] @@ -187,6 +187,9 @@ pub fn check_key(key: &str) -> Result<(), String> { #[derive(Clone, Debug)] pub enum Work { One, + /// One program under a contract, with the planner's reasoning, which its + /// result carries (`engine::planner`). + Planned(Value), Set { items: Vec, plans: Vec }, } @@ -317,6 +320,11 @@ impl Job { if let Work::Set { plans, .. } = &self.work { r["set_plans"] = json!(plans); } + // A contract job's reasoning, as it was admitted: what it runs on was + // decided by it, and its result seals it. + if let Work::Planned(reasoning) = &self.work { + r["planner"] = reasoning.clone(); + } r } } @@ -330,17 +338,9 @@ struct Client { submissions: VecDeque, } -/// One timed job of a method: its work, the time the engine took over it, -/// and its energy figure's power where it has one, for the dry run. -#[derive(Clone, Copy, Debug)] -struct Timing { - work: u64, - elapsed_ms: u64, - watts: Option, -} - -/// The timings a method keeps, at most. -const TIMINGS: usize = 32; +// One timed job of a method, and how many a method keeps: the engine's, which +// the command line's estimates share (engine::energy::estimate). +use wai_quantum::engine::energy::{TIMINGS, Timing}; /// What the service found in its store when it started. #[derive(Clone, Copy, Debug, Default)] @@ -489,6 +489,13 @@ impl Service { Status::Queued => { let cap = s.config.job_mib << 20; let replanned = match &job.work { + // A contract job runs on the route its reasoning chose when it + // was admitted, and that reasoning is what its receipt seals. + Work::Planned(reasoning) => Ok((job.plan.clone(), Work::Planned(reasoning.clone()))), + Work::One if planner::has_contract(&job.request) => planner::decide(wai_quantum::engine::registry::Registry::builtins(), &job.request, &planner::Host::new(cap)).and_then(|d| match d.choice { + planner::Choice::Local(p) => Ok((p, Work::Planned(d.reasoning))), + _ => Err("its contract's route is not on this service".to_string()), + }), Work::One => crate::catalog::plan(&job.request, cap).map(|p| (p, Work::One)), Work::Set { items, .. } => sets::plan(items, cap).map(|plans| (sets::summary(&plans), Work::Set { items: items.clone(), plans })), }; @@ -554,7 +561,10 @@ impl Service { } Work::Set { items, plans } } - None => Work::One, + None => match rec.get("planner") { + Some(reasoning) if reasoning.is_object() => Work::Planned(reasoning.clone()), + _ => Work::One, + }, }; let mut result = None; if rec.get("result").is_some() { @@ -735,7 +745,7 @@ impl Service { self.count(client)?; let unkept = |e: String| Refused(503, tag(refusal::BUSY, format!("the job store could not keep the job ({e}); try again later"))); let programs: Vec<&str> = match &work { - Work::One => request.get("qasm").and_then(Value::as_str).into_iter().collect(), + Work::One | Work::Planned(_) => request.get("qasm").and_then(Value::as_str).into_iter().collect(), Work::Set { items, .. } => items.iter().filter_map(|i| i.request.get("qasm").and_then(Value::as_str)).collect(), }; let mut digests = Digests { request: Some(self.store.put(&canonical).map_err(unkept)?), ..Digests::default() }; @@ -834,12 +844,13 @@ impl Service { let mut t = self.timings.lock().unwrap(); let mut push = |method: &str, work: u64, r: &Value, energy: &Value| { let Some(elapsed_ms) = r["elapsed_ms"].as_u64() else { return }; - let watts = match (energy["joules_micro"].as_u64(), energy["energy_uncertainty"]["window_us"].as_u64()) { + let window_us = energy["energy_uncertainty"]["window_us"].as_u64(); + let watts = match (energy["joules_micro"].as_u64(), window_us) { (Some(uj), Some(us)) if us > 0 => Some(uj as f64 / us as f64), _ => None, }; let q = t.entry(method.to_string()).or_default(); - q.push_back(Timing { work, elapsed_ms, watts }); + q.push_back(Timing { work, elapsed_ms, watts, window_us, partial: energy["coverage"] != "whole" }); if q.len() > TIMINGS { q.pop_front(); } @@ -847,8 +858,8 @@ impl Service { // A metered job was planned at what its meter allows, not at what it // took: its time says nothing of the method's rate. match &job.work { - Work::One if job.plan.metered => {} - Work::One => push(&job.plan.method, job.plan.work, r, &r["energy"]), + Work::One | Work::Planned(_) if job.plan.metered => {} + Work::One | Work::Planned(_) => push(&job.plan.method, job.plan.work, r, &r["energy"]), // A set's items are timed one by one; the set's energy covers them all. Work::Set { plans, .. } => { for (it, p) in r["items"].as_array().into_iter().flatten().zip(plans) { @@ -866,44 +877,38 @@ impl Service { /// each labelled with its basis; and, where such jobs were metered, their /// median power over the estimated time, an estimate and never a reading. pub fn estimate(&self, plan: &Plan) -> (Value, Value) { - let t = self.timings.lock().unwrap(); - let mine: Vec = t.get(&plan.method).map(|q| q.iter().copied().collect()).unwrap_or_default(); - let median = |mut v: Vec| -> Option { - v.retain(|x| x.is_finite() && *x > 0.0); - if v.len() < 3 { - return None; - } - v.sort_by(f64::total_cmp); - Some(v[v.len() / 2]) + let unmetered = match crate::energy::meter() { + crate::energy::Meter::Unmetered(why) => Some(why.as_str()), + _ => None, }; - let rates: Vec = mine.iter().filter(|x| x.elapsed_ms >= 5 && x.work > 0).map(|x| x.work as f64 / (x.elapsed_ms as f64 / 1e3)).collect(); - let n = rates.len(); - let (seconds, basis) = match (median(rates), wai_quantum::engine::catalog::nominal_rate(&plan.method)) { - (Some(rate), _) => (Some(plan.work as f64 / rate), format!("the median rate of the last {n} {} jobs this service timed", plan.method)), - (None, Some(rate)) => (Some(plan.work as f64 / rate), format!("the planner's nominal rate for {} ({rate:.1e} of its work units a second); this service has not yet timed three of its jobs", plan.method)), - (None, None) => (None, format!("the work the planner counts for {} does not predict its time, and this service has not yet timed three of its jobs", plan.method)), + let e = wai_quantum::engine::energy::estimate(plan, &self.timed(plan), "this service", unmetered, self.config.job_timeout.as_secs()); + (e.time, e.energy) + } + + /// What this service says of `plan`'s energy before it runs: an estimate, from + /// the figures it sealed whole, which promises nothing, and what reads the + /// worker while it runs, which is what holds a contract's `max_joules` + /// ([`Service::supervise`]). + pub fn figure(&self, plan: &Plan) -> wai_quantum::engine::energy::Held { + let every = wai_quantum::engine::energy::WATCH_MS; + let (reads, unmetered) = match crate::energy::meter() { + crate::energy::Meter::Process => (Ok(format!("the CPU energy of the job's worker, read every {every} ms; not memory or the host's idle draw")), None), + crate::energy::Meter::Packages(_) => (Ok(format!("the processor packages' energy over the job's window, read every {every} ms: every process on them, so a busy host stops a job sooner; not memory")), None), + crate::energy::Meter::Unmetered(why) => (Err(format!("this host reads no energy: {why}")), Some(why.as_str())), }; - let time = match seconds { - Some(s) => json!({ "seconds": s, "basis": basis, "note": "an estimate: the run is bounded by the job's time limit, not by this" }), - None => json!({ "seconds": null, "why": basis, "at_most": self.config.job_timeout.as_secs() }), + let watch = if wai_quantum::engine::planner::is_gpu(&plan.method) { Err("it runs on the GPU, which no counter here reads".to_string()) } else { reads }; + let whole: Vec = self.timed(plan).into_iter().filter(|t| !t.partial).collect(); + let e = wai_quantum::engine::energy::estimate(plan, &whole, "this service", unmetered, self.config.job_timeout.as_secs()).energy; + let estimate = match e["joules_micro_estimate"].as_u64() { + Some(u) => Ok((u as f64 / 1e6, format!("an estimate, which promises nothing: {}", e["basis"].as_str().unwrap_or("")))), + None => Err(e["unestimated"].as_str().unwrap_or("this service estimates none").to_string()), }; - let powers: Vec = mine.iter().filter_map(|x| x.watts).collect(); - let k = powers.len(); - let energy = match (median(powers), seconds) { - (Some(w), Some(s)) if (w * s * 1e6).round() < 1.0 => json!({ "unestimated": "the estimate is under a microjoule, below what a figure resolves" }), - (Some(w), Some(s)) => json!({ - "joules_micro_estimate": (w * s * 1e6).round() as u64, - "energy_provenance": "Estimator", - "basis": format!("the median power of the last {k} metered {} jobs here, over the estimated time", plan.method), - "note": "an estimate from past readings, never a reading of this job", - }), - _ => json!({ "unestimated": match crate::energy::meter() { - crate::energy::Meter::Unmetered(why) => format!("this host does not meter jobs ({why}), so there is nothing to estimate from"), - _ if seconds.is_none() => "no time estimate to take the power over".to_string(), - _ => format!("this service has not yet metered three {} jobs to estimate from", plan.method), - } }), - }; - (time, energy) + wai_quantum::engine::energy::Held { estimate, watch } + } + + /// The timings kept of `plan`'s method. + fn timed(&self, plan: &Plan) -> Vec { + self.timings.lock().unwrap().get(&plan.method).map(|q| q.iter().copied().collect()).unwrap_or_default() } /// Drops finished jobs older than [`Config::retain`], their records, and @@ -1001,7 +1006,7 @@ impl Service { j.started_ms = Some(now_ms()); let _ = self.keep(j); let input = match &j.work { - Work::One => json!({ "request": j.request, "plan": j.plan }), + Work::One | Work::Planned(_) => json!({ "request": j.request, "plan": j.plan }), Work::Set { items, plans } => json!({ "set": items.iter().zip(plans).map(|(i, p)| json!({ "request": i.request, "plan": p })).collect::>() }), }; Some((input, matches!(j.plan.method.as_str(), "statevector_single" | "cutrank_single") || matches!(&j.work, Work::Set { plans, .. } if plans.iter().any(|p| matches!(p.method.as_str(), "statevector_single" | "cutrank_single"))), others)) @@ -1105,10 +1110,17 @@ impl Service { fn seal(&self, request: &Value, work: &Work, out: Value, figure: Value, elapsed_ms: u64) -> Result<(Value, Value), String> { let signer = self.sealer.get().ok_or("the service has no signing key")?; match work { - Work::One => { + Work::One | Work::Planned(_) => { let mut r = out; // Inside the result, so the receipt seals the figure and its class. r["energy"] = figure; + // A contract's reasoning, and what it kept against the figure. + if let Work::Planned(reasoning) = work { + planner::complete(&mut r, reasoning)?; + planner::finish(request, &mut r, None); + // The service gives no receipt its own verifier refuses. + planner::own_check(request, &r)?; + } signer.seal_into(request, &mut r); let receipt = r.as_object_mut().and_then(|o| o.shift_remove("receipt")).ok_or("a result has a receipt")?; Ok((r, receipt)) @@ -1174,10 +1186,25 @@ impl Service { }); // The admitted memory, with room for the process itself. let limit = (mib + 256) << 20; - let deadline = Instant::now() + self.config.job_timeout; + // A contract's deadline, where it is sooner than the job's limit: this host + // can stop a run, so one past it is stopped. + let asked = planner::Contract::read(&input["request"]).ok().flatten().and_then(|c| c.deadline_seconds).and_then(|d| Duration::try_from_secs_f64(d).ok()).filter(|d| *d < self.config.job_timeout); + let deadline = Instant::now() + asked.unwrap_or(self.config.job_timeout); + // A contract's energy ceiling, held by a live reading of the worker: a + // package's counter is added up as it is read, so that it can wrap. + let ceiling = planner::Contract::read(&input["request"]).ok().flatten().and_then(|c| c.max_joules); + // The packages' counter added up read by read, every look: what the job + // took in all, however many ranges it passes. + let mut packages = match meter { + energy::Meter::Packages(p) => before.clone().map(|b| wai_quantum::engine::energy::Accumulated::new(p, b)), + _ => None, + }; + let mut watcher = ceiling.map(wai_quantum::engine::energy::Watcher::new); + let mut stopped = None; + let mut stopped_figure = Value::Null; let mut peak = 0u64; let mut reading = None; - let mut after = None; + let mut ended_at: Option<()> = None; let why = loop { // The worker's energy is readable only between its exit and its // reaping, so it is reaped only once it has been seen to exit and @@ -1190,8 +1217,9 @@ impl Service { if exited != Some(false) { match child.try_wait() { Ok(Some(status)) => { - if let energy::Meter::Packages(p) = meter { - after = p.read(); + // The packages read once more, at the exit, and added up. + if let Some(added) = packages.as_mut() { + ended_at = added.read().map(|_| ()); } break status.success().then_some(()).ok_or(format!("the worker ended: {status}")); } @@ -1207,16 +1235,76 @@ impl Service { break Err(format!("the job used {} MiB, over the {} MiB it was admitted with; it was stopped", rss >> 20, mib)); } } + let looked = packages.as_mut().and_then(|added| added.read()); + if let Some(w) = &mut watcher { + let (now, cpu) = match meter { + energy::Meter::Process => wai_quantum::engine::energy::running(pid).map_or((None, None), |r| (Some(r.joules()), Some(r.cpu_ns))), + energy::Meter::Packages(_) => (looked, None), + energy::Meter::Unmetered(_) => (None, None), + }; + match w.take_with(now, cpu) { + Some(wai_quantum::engine::energy::Watched::Reached(joules)) => { + kill(pid); + let elapsed_ms = began.elapsed().as_millis() as u64; + // What the worker took in all, read after the kill and before + // it is reaped, where it can be. + stopped_figure = match meter { + energy::Meter::Process => { + let mut whole = None; + for _ in 0..2000 { + if energy::exited_unreaped(pid) == Some(true) { + whole = energy::read(pid); + break; + } + tokio::time::sleep(Duration::from_millis(1)).await; + } + let _ = child.wait().await; + energy::figure(whole.as_ref(), gpu, "the worker could not be read after it was stopped") + } + energy::Meter::Packages(_) => { + let _ = child.wait().await; + let concurrent = others + self.starts.load(Ordering::SeqCst).saturating_sub(start); + let r = packages.as_mut().and_then(|added| added.read().map(|_| added.reading(concurrent))); + energy::package_figure(r.as_ref(), "the processor packages' counter did not read when the worker was stopped") + } + energy::Meter::Unmetered(why) => { + let _ = child.wait().await; + json!({ "unmetered": why }) + } + }; + let read = match meter { + energy::Meter::Process => "the CPU energy of the job's worker, read about every 10 ms as the host schedules the service", + _ => "the processor packages' energy over the job's window, read about every 10 ms as the host schedules the service: every process on them", + }; + stopped = Some(planner::Stopped { joules, elapsed_ms, read: w.said(read) }); + break Ok(()); + } + Some(_) => { + kill(pid); + let _ = child.wait().await; + break Err("the counter holding the job's energy ceiling stopped reading, so it was stopped".to_string()); + } + None => {} + } + } if Instant::now() > deadline { kill(pid); let _ = child.wait().await; - break Err(format!("the job ran past {} s; it was stopped", self.config.job_timeout.as_secs())); + break Err(match asked { + Some(d) => tag(refusal::DEADLINE_PASSED, format!("the job ran past its contract's deadline of {} s, though it was planned to take less; it was stopped, and nothing was sealed", d.as_secs_f64())), + None => format!("the job ran past {} s; it was stopped", self.config.job_timeout.as_secs()), + }); } + // Never past the deadline by more than a step: a contract's deadline is + // held to the millisecond, not to the next look at the worker. + let look = if watcher.is_some() { wai_quantum::engine::energy::WATCH_MS } else { 200 }; + let step = Duration::from_millis(look).min(deadline.saturating_duration_since(Instant::now()) + Duration::from_millis(1)); if exited.is_none() { - match tokio::time::timeout(Duration::from_millis(200), child.wait()).await { + match tokio::time::timeout(step, child.wait()).await { Ok(Ok(status)) => { - if let energy::Meter::Packages(p) = meter { - after = p.read(); + // The packages read once more, at the exit, and added up. + if let Some(added) = packages.as_mut() { + ended_at = added.read().map(|_| ()); } break status.success().then_some(()).ok_or(format!("the worker ended: {status}")); } @@ -1224,12 +1312,18 @@ impl Service { Err(_) => {} } } else { - tokio::time::sleep(Duration::from_millis(200)).await; + tokio::time::sleep(step).await; } }; let elapsed_ms = began.elapsed().as_millis() as u64; let out = reader.await.unwrap_or_default(); let err = errors.await.unwrap_or_default(); + // Stopped at its ceiling: no answer, and a receipt that says so. + if let Some(s) = stopped { + let Some(plan) = self.jobs.lock().unwrap().get(id).map(|j| j.plan.clone()) else { return failed("the job is gone".into()) }; + let result = planner::stopped_result(wai_quantum::engine::registry::Registry::builtins(), &input["request"], &plan, &Value::Null, &s); + return Ran { outcome: Ok(result), peak, energy: stopped_figure, elapsed_ms }; + } if let Err(e) = why { let detail = String::from_utf8_lossy(&err); let detail = detail.trim(); @@ -1240,8 +1334,8 @@ impl Service { let concurrent = others + self.starts.load(Ordering::SeqCst).saturating_sub(start); let figure = match meter { energy::Meter::Process => energy::figure(reading.as_ref(), gpu, energy::UNMETERED_HERE), - energy::Meter::Packages(p) => { - let r = before.as_ref().zip(after.as_ref()).and_then(|(b, a)| p.between(b, a, concurrent)); + energy::Meter::Packages(_) => { + let r = ended_at.and(packages.as_ref()).map(|added| added.reading(concurrent)); energy::package_figure(r.as_ref(), "the processor packages' counter did not read at the job's start or end") } energy::Meter::Unmetered(why) => json!({ "unmetered": why }), @@ -1285,6 +1379,8 @@ fn low_priority(exe: &std::path::Path, sandbox: bool) -> tokio::process::Command c }; cmd.arg("worker"); + // The worker's death-link compares its parent with this process, whatever pid it has. + cmd.env("WAI_QSVC_PARENT", std::process::id().to_string()); cmd } @@ -1503,6 +1599,37 @@ mod tests { let _ = std::fs::remove_dir_all(&dir); } + /// A contract job queued when the service stopped keeps the reasoning it was + /// admitted with: the route it runs on, and what its receipt seals. Decided + /// again on a service that has metered nothing yet, its energy ceiling would + /// refuse it. + #[test] + fn a_contract_job_keeps_its_reasoning_across_a_restart() { + use wai_quantum::engine::{planner, registry::Registry}; + let dir = store_dir("contract"); + let req = json!({ "qasm": "OPENQASM 3.0; qubit q; h q;", "shots": 5, "contract": { "exactness": "exact", "max_joules": 10 } }); + let metered = |_: &Plan| wai_quantum::engine::energy::Held { estimate: Ok((0.5, "a test's figure".to_string())), watch: Ok("a test's reading".to_string()) }; + let d = planner::decide(Registry::builtins(), &req, &planner::Host::new(1 << 30).with_joules(&metered)).unwrap(); + let planner::Choice::Local(p) = d.choice else { panic!("{}", d.reasoning) }; + // Asked again with nothing metered, the same contract has no route. + assert!(planner::decide(Registry::builtins(), &req, &planner::Host::new(1 << 30)).unwrap_err().ends_with("[J071]")); + let id; + { + let s = Service::with_store(config(), Box::new(store::Files::open(&dir.join("store")).unwrap())); + id = s.submit_work("a", req.clone(), p.clone(), Work::Planned(d.reasoning.clone()), None).unwrap(); + } + let s = Service::open(config(), Box::new(store::Files::open(&dir.join("store")).unwrap())).unwrap(); + assert_eq!(s.get(&id).unwrap()["status"], "queued", "{}", s.get(&id).unwrap()); + { + let jobs = s.jobs.lock().unwrap(); + let j = jobs.get(&id).unwrap(); + assert!(matches!(&j.work, Work::Planned(r) if *r == d.reasoning), "{:?}", j.work); + assert_eq!(j.plan.method, p.method); + } + drop(s); + let _ = std::fs::remove_dir_all(&dir); + } + /// A job that was running when the service stopped runs again, once, /// from its stored request: queued in its order, it finishes with a /// receipt that verifies. Stopped again while it runs, it is @@ -1824,12 +1951,42 @@ mod tests { assert!(t["seconds"].is_null() && t["at_most"] == 5, "{t}"); // Timed jobs here take over, and their metered power gives an energy estimate. for _ in 0..3 { - let job = Job { id: job_id(), client: "x".into(), request: json!({}), plan: Plan { work: 1_000_000_000, ..p.clone() }, work: Work::One, status: Status::Done, submitted_ms: 0, started_ms: None, finished_ms: Some(1), result: Some(json!({ "elapsed_ms": 500, "energy": { "joules_micro": 5_000_000, "energy_uncertainty": { "window_us": 500_000 } } })), error: None, peak_rss: 0, digests: Digests::default(), key: None, interruptions: Vec::new(), child: None }; + let job = Job { id: job_id(), client: "x".into(), request: json!({}), plan: Plan { work: 1_000_000_000, ..p.clone() }, work: Work::One, status: Status::Done, submitted_ms: 0, started_ms: None, finished_ms: Some(1), result: Some(json!({ "elapsed_ms": 500, "energy": { "joules_micro": 5_000_000, "coverage": "whole", "energy_uncertainty": { "window_us": 500_000 } } })), error: None, peak_rss: 0, digests: Digests::default(), key: None, interruptions: Vec::new(), child: None }; s.time(&job); } let (t, e) = s.estimate(&p); assert!((t["seconds"].as_f64().unwrap() - 1.0).abs() < 1e-9 && t["basis"].as_str().unwrap().contains("this service timed"), "{t}"); assert_eq!(e["joules_micro_estimate"], 10_000_000, "{e}"); assert_eq!(e["energy_provenance"], "Estimator"); + // What a dry run has always said, word for word. + assert_eq!(t["basis"], "the median rate of the last 3 statevector jobs this service timed"); + assert_eq!(t["note"], "an estimate: the run is bounded by the job's time limit, not by this"); + assert_eq!(e["basis"], "the median power of the last 3 metered statevector jobs here, over the estimated time"); + assert_eq!(e["note"], "an estimate from past readings, never a reading of this job"); + } + + /// What the service says of a plan before it runs: an estimate, from what it + /// sealed whole, which promises nothing, and what would read the worker, which + /// is what holds a ceiling. A method on the GPU has no reading of what does the + /// work; a figure that leaves part of a job out estimates nothing. + #[test] + fn a_route_s_figure_is_an_estimate_and_what_reads_the_run() { + let s = Service::new(config()); + let p = Plan { method: "statevector".into(), why: "".into(), memory_bytes: 1, work: 2_000_000_000, qubits: 20, target: None, metered: false }; + let job = |coverage: &str| Job { id: job_id(), client: "x".into(), request: json!({}), plan: Plan { work: 1_000_000_000, ..p.clone() }, work: Work::One, status: Status::Done, submitted_ms: 0, started_ms: None, finished_ms: Some(1), result: Some(json!({ "elapsed_ms": 500, "energy": { "joules_micro": 5_000_000, "coverage": coverage, "energy_uncertainty": { "window_us": 500_000 } } })), error: None, peak_rss: 0, digests: Digests::default(), key: None, interruptions: Vec::new(), child: None }; + assert!(s.figure(&p).estimate.is_err()); + for _ in 0..3 { + s.time(&job("partial")); + } + assert!(s.figure(&p).estimate.is_err(), "what leaves part of a job out estimates no job"); + for _ in 0..3 { + s.time(&job("whole")); + } + let (joules, basis) = s.figure(&p).estimate.unwrap(); + assert_eq!(joules, 10.0); + assert!(basis.starts_with("an estimate, which promises nothing") && basis.contains("median power"), "{basis}"); + // The GPU's methods: what the worker read leaves out what does the work. + let gpu = Plan { method: "statevector_single".into(), ..p.clone() }; + assert!(matches!(s.figure(&gpu).watch, Err(w) if w.contains("the GPU"))); } } diff --git a/wai/wai-quantum-service/src/main.rs b/wai/wai-quantum-service/src/main.rs index ce3b2ff7b..41c3360af 100644 --- a/wai/wai-quantum-service/src/main.rs +++ b/wai/wai-quantum-service/src/main.rs @@ -73,15 +73,34 @@ fn usage() { fn watch_parent() { #[cfg(unix)] { - let parent = std::os::unix::process::parent_id(); - std::thread::spawn(move || { + // The service that started this worker, as it said: a service that is a + // namespace's first process (pid 1) is a parent like any other. + let parent = std::env::var("WAI_QSVC_PARENT").ok().and_then(|p| p.parse::().ok()).unwrap_or_else(std::os::unix::process::parent_id); + // On Linux the kernel kills a worker whose service has died. + #[cfg(target_os = "linux")] + { + unsafe extern "C" { + fn prctl(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> i32; + } + /// `PR_SET_PDEATHSIG` and `SIGKILL`. + const PR_SET_PDEATHSIG: i32 = 1; + // SAFETY: it sets this process's own death signal. + let _ = unsafe { prctl(PR_SET_PDEATHSIG, 9, 0, 0, 0) }; + } + if std::os::unix::process::parent_id() != parent { + std::process::exit(3); + } + let watching = std::thread::Builder::new().spawn(move || { loop { - std::thread::sleep(std::time::Duration::from_millis(500)); + std::thread::sleep(std::time::Duration::from_millis(100)); if std::os::unix::process::parent_id() != parent { std::process::exit(3); } } }); + if watching.is_err() { + std::process::exit(3); + } } } @@ -114,6 +133,9 @@ fn worker() { Err(e) => serde_json::json!({ "error": format!("the job is not JSON: {e}") }), }; println!("{out}"); + // Off the core before it exits, so that the counter takes in its last stretch + // (on Apple silicon a thread's energy is added as it leaves a core). + std::thread::sleep(std::time::Duration::from_millis(5)); } /// The host a result's provenance names. diff --git a/wai/wai-quantum-service/src/mcp.rs b/wai/wai-quantum-service/src/mcp.rs index 6c3265fce..36dd273c9 100644 --- a/wai/wai-quantum-service/src/mcp.rs +++ b/wai/wai-quantum-service/src/mcp.rs @@ -234,19 +234,24 @@ fn tool_list() -> Value { "mitigate": wai_quantum::engine::mitigate::schema(), "pulse": wai_quantum::engine::pulse::options_schema(), "source": wai_quantum::engine::formats::source_schema(), - "params": { "type": "object", "additionalProperties": { "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes." } + "params": { "type": "object", "additionalProperties": { "type": "number" }, "description": "A value for each of the program's parameters (input float theta;, input angle phi;), as {\"theta\": 0.3}: bound exactly before the program is read; a parameter left without one is refused (J050). In a sweep, the parameters it fixes." }, + "contract": wai_quantum::engine::planner::contract_schema() }); let mut on_target = json!({ "type": "object", "required": ["target"], "anyOf": wai_quantum::engine::formats::program_required(), "properties": job_props.clone() }); on_target["properties"].as_object_mut().map(|o| o.remove("method")); // A set: the job's fields, shared by every item, and its programs or its sweep. let mut set_props = job_props.clone(); - set_props.as_object_mut().map(|o| o.remove("source")); + if let Some(o) = set_props.as_object_mut() { + o.remove("source"); + o.remove("contract"); + } set_props["qasm"] = json!({ "type": "string", "description": "With sweep: the program, which declares the inputs the sweep gives values (`input uint n;`, `input float theta;`, `input angle phi;`)." }); set_props["programs"] = json!({ "type": "array", "minItems": 1, "maxItems": wai_quantum::engine::sets::MAX_ITEMS, "items": { "anyOf": [{ "type": "string" }, { "type": "object", "required": ["qasm"] }] }, "description": "The set's programs: each a program's text, or a job ({\"qasm\", …}) whose own fields win over the set's." }); set_props["sweep"] = json!({ "type": "object", "additionalProperties": { "type": "array", "minItems": 1, "items": { "type": "number" } }, "description": "Each input of qasm and its values: every combination runs, the names in sorted order, the first varying slowest; an integer input's values are whole numbers." }); let mut plan_props = set_props.clone(); plan_props["qasm"] = job_props["qasm"].clone(); plan_props["source"] = job_props["source"].clone(); + plan_props["contract"] = job_props["contract"].clone(); // A run's key, which a plan does not take. let key = json!({ "type": "string", "minLength": 1, "maxLength": crate::jobs::KEY_MAX, "pattern": "^[!#-\\[\\]-~]+$", "description": "A key of your making that names this run, so that a call sent again is not a second job: the same key with the same arguments answers with the job it names, for as long as the job is kept, rather than running another; the same key with other arguments is refused (J034). Make it unguessable (a UUID). A job the service interrupted is run again under its key. Without a key, every call is a new job." }); for props in [&mut job_props, &mut set_props, &mut on_target["properties"]] { diff --git a/wai/wai-quantum-service/tests/contract.rs b/wai/wai-quantum-service/tests/contract.rs new file mode 100644 index 000000000..8c074a3c3 --- /dev/null +++ b/wai/wai-quantum-service/tests/contract.rs @@ -0,0 +1,232 @@ +//! A contract on the free job service, over HTTP, with its worker: what meets it +//! runs, its reasoning sealed; what does not is refused with every route's +//! reason; the service never reaches a provider; and a deadline it can hold a run +//! to, it holds. + +use serde_json::{Value, json}; +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::path::Path; +use std::process::{Child, Command, Stdio}; +use std::time::{Duration, Instant}; + +fn free_port() -> u16 { + TcpListener::bind("127.0.0.1:0").unwrap().local_addr().unwrap().port() +} + +fn http(port: u16, method: &str, path: &str, body: Option<&Value>) -> (u16, Value) { + let mut s = TcpStream::connect(("127.0.0.1", port)).unwrap(); + s.set_read_timeout(Some(Duration::from_secs(120))).unwrap(); + let text = body.map(Value::to_string).unwrap_or_default(); + write!(s, "{method} {path} HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{text}", text.len()).unwrap(); + let mut out = String::new(); + s.read_to_string(&mut out).unwrap(); + let status = out.split_whitespace().nth(1).and_then(|c| c.parse().ok()).unwrap_or(0); + let body = out.split_once("\r\n\r\n").map(|(_, b)| b.to_string()).unwrap_or_default(); + (status, serde_json::from_str(&body).unwrap_or(Value::Null)) +} + +fn start(dir: &Path, port: u16) -> Child { + start_with(dir, port, "0") +} + +fn start_with(dir: &Path, port: u16, energy: &str) -> Child { + let child = Command::new(env!("CARGO_BIN_EXE_wai-quantum-service")) + .arg("serve") + .env("WAI_QSVC_ADDR", format!("127.0.0.1:{port}")) + .env("WAI_QSVC_STORE", dir.join("store")) + .env("WAI_QSVC_KEY", dir.join("signing.key")) + .env("WAI_QSVC_JOB_GB", "2") + .env("WAI_QSVC_BUDGET_GB", "4") + .env("WAI_QSVC_WORKERS", "1") + .env("WAI_QSVC_ENERGY", energy) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .expect("the service starts"); + let t = Instant::now(); + while TcpStream::connect(("127.0.0.1", port)).is_err() || http(port, "GET", "/v1/health", None).0 != 200 { + assert!(t.elapsed() < Duration::from_secs(60), "the service did not answer"); + std::thread::sleep(Duration::from_millis(50)); + } + child +} + +fn until_done(port: u16, id: &str) -> Value { + let t = Instant::now(); + loop { + let (_, j) = http(port, "GET", &format!("/v1/jobs/{id}"), None); + if ["done", "failed", "cancelled", "interrupted"].contains(&j["status"].as_str().unwrap_or("")) { + return j; + } + assert!(t.elapsed() < Duration::from_secs(120), "{id} did not finish: {j}"); + std::thread::sleep(Duration::from_millis(50)); + } +} + +struct Service(Child, std::path::PathBuf); + +impl Drop for Service { + fn drop(&mut self) { + let _ = self.0.kill(); + let _ = self.0.wait(); + let _ = std::fs::remove_dir_all(&self.1); + } +} + +const BELL: &str = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"; + +#[test] +fn a_contract_is_met_or_refused_and_the_service_never_reaches_a_provider() { + let dir = std::env::temp_dir().join(format!("wai-qsvc-contract-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + let port = free_port(); + let _service = Service(start(&dir, port), dir.clone()); + + // Met: its reasoning sealed, and the receipt held to it. + let req = json!({ "qasm": BELL, "shots": 200, "contract": { "exactness": "exact", "deadline_seconds": 60, "providers": "allowed" } }); + let (code, made) = http(port, "POST", "/v1/jobs", Some(&req)); + assert_eq!(code, 202, "{made}"); + let job = until_done(port, made["id"].as_str().unwrap()); + assert_eq!(job["status"], "done", "{job}"); + let r = &job["result"]; + assert_eq!(r["planner"]["choice"], "method:stabilizer", "{}", r["planner"]); + let c = wai_quantum::engine::job::check(&job); + assert!(c.valid(), "{:?}", c.reasons); + assert_eq!(r["planner"]["host"]["providers"], json!([]), "the service brings none"); + assert!(r["planner"]["routes"].as_array().unwrap().iter().all(|x| x["kind"] == "local"), "{}", r["planner"]); + assert_eq!(r["planner"]["kept"]["deadline"]["kept"], true, "{}", r["planner"]["kept"]); + assert_eq!(r["planner"]["stable"]["choice"], false, "providers allowed makes a choice the host's"); + // The same again, what a host that reaches none owes: run for this job alone. + let plain = json!({ "qasm": BELL, "shots": 200 }); + let (_, made) = http(port, "POST", "/v1/jobs", Some(&plain)); + let plain_job = until_done(port, made["id"].as_str().unwrap()); + assert_eq!(plain_job["result"]["counts"], r["counts"], "the same seed, the same method, the same counts"); + assert!(plain_job["result"].get("planner").is_none()); + + // A dry run shows every route, and the refused one every reason. + let (_, dry) = http(port, "POST", "/v1/jobs", Some(&json!({ "qasm": BELL, "dry_run": true, "contract": { "exactness": "exact" } }))); + assert_eq!((dry["accepted"].as_bool(), dry["method"].as_str(), dry["planner"]["choice"].as_str()), (Some(true), Some("stabilizer"), Some("method:stabilizer")), "{dry}"); + let (_, dry) = http(port, "POST", "/v1/jobs", Some(&json!({ "qasm": BELL, "dry_run": true, "contract": { "exactness": "measured", "providers": "allowed" } }))); + assert_eq!((dry["accepted"].as_bool(), dry["refusal"]["code"].as_str()), (Some(false), Some("J071")), "{dry}"); + assert!(dry["planner"]["routes"].as_array().unwrap().iter().all(|x| x["rejected"]["code"] == "class" || x["rejected"]["code"] == "cannot"), "{dry}"); + + // Asked for a device, for a provider by name, or for energy it has not metered: refused. + for (req, code_want) in [ + (json!({ "qasm": BELL, "contract": { "exactness": "measured", "providers": "allowed" } }), "J071"), + (json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "allowed" } }), "J002"), + (json!({ "qasm": BELL, "contract": { "max_joules": 1000 } }), "J071"), + (json!({ "qasm": BELL, "contract": { "exact": true } }), "J070"), + (json!({ "programs": [BELL, BELL], "contract": {} }), "J073"), + ] { + let (code, body) = http(port, "POST", "/v1/jobs", Some(&req)); + assert_eq!(code, 400, "{req}: {body}"); + assert_eq!(body["code"], code_want, "{req}: {body}"); + } + + // A run past its deadline is stopped: this one's nominal time counts its state, + // and its million shots are what takes the time. The service looks at the + // worker again at the deadline itself, not at its next round 200 ms on, so a + // run that would end within that round is stopped all the same. + let slow = json!({ "qasm": "OPENQASM 3.0;\nqubit[24] q;\nbit[24] c;\nrx(0.3) q[0];\nc = measure q;\n", "method": "statevector", "shots": 1000000, "contract": { "deadline_seconds": 0.05 } }); + let (code, made) = http(port, "POST", "/v1/jobs", Some(&slow)); + assert_eq!(code, 202, "{made}"); + let job = until_done(port, made["id"].as_str().unwrap()); + assert_eq!(job["status"], "failed", "{job}"); + assert!(job["error"].as_str().unwrap().ends_with("[J074]"), "{job}"); + assert!(job.get("result").is_none(), "nothing was sealed: {job}"); +} + +/// A ceiling is held while the job runs: with the service's meter on, a live reading +/// of the worker stops it at the ceiling, and the receipt says so. Where nothing +/// reads the worker, the route is refused: that is the meter off, in the test above. +#[test] +fn a_job_is_stopped_at_its_energy_ceiling_and_its_receipt_says_so() { + let dir = std::env::temp_dir().join(format!("wai-qsvc-ceiling-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + let port = free_port(); + let mut service = start_with(&dir, port, "1"); + let (_, about) = http(port, "GET", "/v1", None); + if about["energy"]["meter"] == "unmetered" || about["energy"].get("meter").is_none() { + println!("nothing reads a worker on this host: {}", about["energy"]); + let _ = service.kill(); + let _ = service.wait(); + if cfg!(target_os = "macos") { + panic!("a Mac reads its worker's energy, so this test may not pass by skipping"); + } + return; + } + let slow = json!({ "qasm": "OPENQASM 3.0;\nqubit[24] q;\nbit[24] c;\nrx(0.3) q[0];\nc = measure q;\n", "method": "statevector", "shots": 1000000, "contract": { "max_joules": 0.01 } }); + let (code, made) = http(port, "POST", "/v1/jobs", Some(&slow)); + // A host whose worker nothing reads refuses the route, with why. + if code == 400 && made["code"] == "J071" && made["error"].as_str().is_some_and(|e| e.contains("reads no energy")) { + let _ = service.kill(); + let _ = service.wait(); + if cfg!(target_os = "macos") { + panic!("a Mac reads its worker's energy, so this test may not pass by skipping: {made}"); + } + return; + } + assert_eq!(code, 202, "{made}"); + let job = until_done(port, made["id"].as_str().unwrap()); + let _ = service.kill(); + let _ = service.wait(); + let _ = std::fs::remove_dir_all(&dir); + assert_eq!(job["status"], "done", "{job}"); + let r = &job["result"]; + assert_eq!(r["stopped"]["at"], "max_joules", "{r}"); + assert!(r["stopped"]["joules"].as_f64().unwrap() >= 0.01 && r.get("counts").is_none(), "{r}"); + assert_eq!(r["planner"]["kept"]["energy"]["kept"], false, "{}", r["planner"]["kept"]); + assert_eq!(r["accuracy"]["class"], "none"); + // What the killed worker took in all is sealed, with the longest time between reads. + let whole = r["energy"]["joules_micro"].as_u64().map(|u| u as f64 / 1e6); + assert!(whole.is_some_and(|w| w >= r["stopped"]["joules"].as_f64().unwrap()), "{}", r["energy"]); + assert!(r["stopped"]["read"].as_str().unwrap().contains("the longest time between two reads"), "{}", r["stopped"]); + let body = json!({ "request": job["request"], "result": r }); + assert!(wai_quantum::engine::job::check(&body).valid(), "{:?}", wai_quantum::engine::job::check(&body).reasons); +} + +/// The service as a namespace's first process (pid 1), as a container runs it with +/// no init: its workers are its children like any others, and run. +#[cfg(target_os = "linux")] +#[test] +fn the_service_runs_its_jobs_as_pid_1() { + let can = Command::new("unshare").args(["--user", "--pid", "--fork", "true"]).status(); + if !can.is_ok_and(|s| s.success()) { + println!("this host makes no user and pid namespace for this user"); + return; + } + let dir = std::env::temp_dir().join(format!("wai-qsvc-pid1-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + let port = free_port(); + let mut service = Command::new("unshare") + .args(["--user", "--pid", "--fork"]) + .arg(env!("CARGO_BIN_EXE_wai-quantum-service")) + .arg("serve") + .env("WAI_QSVC_ADDR", format!("127.0.0.1:{port}")) + .env("WAI_QSVC_STORE", dir.join("store")) + .env("WAI_QSVC_KEY", dir.join("signing.key")) + .env("WAI_QSVC_JOB_GB", "2") + .env("WAI_QSVC_BUDGET_GB", "4") + .env("WAI_QSVC_WORKERS", "1") + .env("WAI_QSVC_ENERGY", "0") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .unwrap(); + let t = Instant::now(); + while TcpStream::connect(("127.0.0.1", port)).is_err() { + assert!(t.elapsed() < Duration::from_secs(60), "the service did not answer"); + std::thread::sleep(Duration::from_millis(50)); + } + let bell = json!({ "qasm": "OPENQASM 3.0; qubit[2] q; bit[2] c; h q[0]; cx q[0], q[1]; c = measure q;", "shots": 100 }); + let (code, done) = http(port, "POST", "/v1/run", Some(&bell)); + let _ = service.kill(); + let _ = service.wait(); + let _ = std::fs::remove_dir_all(&dir); + assert_eq!((code, done["status"].as_str()), (200, Some("done")), "{done}"); +} + diff --git a/wai/wai-quantum-views/README.md b/wai/wai-quantum-views/README.md index d85e72585..21b1ba3d7 100644 --- a/wai/wai-quantum-views/README.md +++ b/wai/wai-quantum-views/README.md @@ -29,9 +29,11 @@ of the binary), optimises it for size and translates it to JavaScript with binaryen, and runs `wai/quantum-studio/build-views.mjs`, which bundles the views (`wai/quantum-studio/src/views/`, from the Studio's components) and writes the page and its `manifest.json`: each part's size and SHA-256, and -every source with its SHA-256. The page is 802 KB: the script 94 KB (the -Studio's English words among it), the styles 49 KB, the engine 194 KB as -WebAssembly (258 KB in base64) and 401 KB as JavaScript. Every view is held under 1 MiB. +every source with its SHA-256. The page is 880 KB: the script 94 KB (the +Studio's English words among it), the styles 50 KB, the engine 274 KB as +WebAssembly, carried raw-deflated (131 KB, 175 KB in base64) and inflated by +the page with the platform's `DecompressionStream`, and 561 KB as JavaScript. +Every view is held under 1 MiB. On x86_64 Linux with Rust 1.98.0 the build gives the same bytes in a clean CI image. The engine's bytes change when anything in `wai-quantum` changes (its diff --git a/wai/wai-quantum/README.md b/wai/wai-quantum/README.md index 8339148a7..d1a768d2a 100644 --- a/wai/wai-quantum/README.md +++ b/wai/wai-quantum/README.md @@ -799,7 +799,7 @@ receipt marker by running it again. Its conformance set is circuit, a result with its verdict, a receipt, a critique, an estimate's frontier, a device target's map) to an agent host through the Model Context Protocol's extension for them (`io.modelcontextprotocol/ui`, 2026-01-26): -`ui://wai-quantum/*` resources, one self-contained page of 802 KB held under +`ui://wai-quantum/*` resources, one self-contained page of 880 KB held under 1 MiB (`views/`, built by `wai/wai-quantum-views/build.sh`), which checks the receipt of what it shows with the engine inside it, as WebAssembly or, under a policy that refuses WebAssembly, translated to JavaScript. Both MCP servers diff --git a/wai/wai-quantum/docs/job-refusals.md b/wai/wai-quantum/docs/job-refusals.md index 07210d108..832c0649d 100644 --- a/wai/wai-quantum/docs/job-refusals.md +++ b/wai/wai-quantum/docs/job-refusals.md @@ -85,6 +85,11 @@ browser engine. A test holds this page to the code's table. | `J063` | refused | A component the registry does not take: a name its kind holds already (a built-in's among them), a name or version that is empty or not plain text, a descriptor that is not a JSON object, a channel on other than one or two qubits, or a pass whose check states no bound. | | `J064` | refused | A registered component's answer that breaks the engine's contract: a method's result without an accuracy class it declared, or one that writes a member the engine writes (method, qubits, gates, compiled, repaired, engine, schema, components, receipt, verdict); a pass's gates on qubits the program does not have, or that do not read back; a front end's program that does not read. Nothing it gave is returned. | | `J065` | refused | An intent on a job whose noise names a registered channel: the intent checks model the built-in channels alone, so the check is refused rather than made against another model. | +| `J070` | refused | A contract that does not read: not an object, a member a contract does not have, an exactness that is no class, a max_cost that is not an amount in decimals and a currency, a deadline or an energy ceiling that is not above zero, providers that is neither never nor allowed, or a job that names a provider while its contract does not allow one (providers: never is the default). | +| `J071` | refused | No route this host can see meets the contract: each route's price or reason is listed, so the contract or the job can be changed. Nothing fell back to a route the contract does not allow. | +| `J072` | refused | A route's result whose accuracy class does not meet the class its job wants: the contract's, or under a contract that names none the class the job keeps. Nothing it gave is returned, since its receipt would not verify. | +| `J073` | refused | A contract where it cannot be honoured: on a set or an item of one (each program runs under its own contract, alone), or on a build with no planner. It is refused rather than read as absent. | +| `J074` | refused | A run stopped at its contract's deadline, by a host that can stop one: the job service's worker, or a provider's job the command line cancels where it waits. The estimate it was planned on was wrong here, and nothing was sealed. | | `J100` | dropped | A line of an answer that is not a statement (`name = View(...)`), a program (a fenced `qasm` block with its name), a comment or a marker: left out. | | `J101` | dropped | A view the answer layer does not have: left out (the views are listed in the layer's specification). | | `J102` | dropped | An `@` call the engine does not have: the statement is left out. | diff --git a/wai/wai-quantum/schemas/job-request.v1.json b/wai/wai-quantum/schemas/job-request.v1.json index 697d35c2c..36dc95398 100644 --- a/wai/wai-quantum/schemas/job-request.v1.json +++ b/wai/wai-quantum/schemas/job-request.v1.json @@ -411,6 +411,78 @@ } } } + }, + "contract": { + "description": "What the job wants of an answer (wai/extensions/quantum-providers.md section 8.7). Every route the host can see is priced with what is really known, those that cannot meet this are rejected, the cheapest of the rest runs, and the reasoning is sealed in the result as `planner`. Nothing falls back in silence, and a job no route can meet is refused (J071). A job without it plans as it always has, byte for byte. Refused on a set (J073).", + "type": [ + "object", + "null" + ], + "additionalProperties": false, + "properties": { + "exactness": { + "description": "The class wanted. Without it, the job keeps the class auto would give: auto's pick stands while it meets the rest of the contract, and only a route at least as exact may take its place. A device's counts are in no classical class: measured wants a processor's, simulated a provider's simulator's that its provider does not state is approximate, and any takes every route.", + "enum": [ + "bit-exact", + "exact", + "single", + "bounded", + "estimate", + "heuristic", + "measured", + "simulated", + "any", + null + ] + }, + "max_cost": { + "description": "The most a provider's estimate of the run may come to, before it runs: it bounds the estimate, not the charge, which is stated after the run beside it (kept.cost). A route with an unknown cost, an estimate that is only the least it can come to, or a price in another currency does not meet it: nothing is converted.", + "type": [ + "object", + "null" + ], + "required": [ + "amount", + "currency" + ], + "additionalProperties": false, + "properties": { + "amount": { + "type": "string", + "description": "An amount in decimals: digits, and optionally a point and digits, at most 64 characters.", + "maxLength": 64 + }, + "currency": { + "type": "string", + "minLength": 1 + } + } + }, + "deadline_seconds": { + "description": "When it must be done by, in seconds from when it starts. A route whose time is not known does not meet it. A host that can stop a run stops it there (J074); otherwise the result says whether it was kept.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "max_joules": { + "description": "The most energy it may take, held by a live reading while it runs: at the ceiling the run is stopped, gives no answer, and its receipt says so. A route nothing here can read and stop does not meet it, so on a host that reads none every route is rejected. An estimate can refuse a job clearly past it, and promises nothing.", + "type": [ + "number", + "null" + ], + "exclusiveMinimum": 0 + }, + "providers": { + "description": "Whether a route may be one of the person's providers. never is the default, given or not: a job that names a provider under a contract that does not allow one is refused (J070), and a host asks no provider anything under it. A host that reaches none (the job service) lists none. A provider that costs money is chosen only under max_cost, or when the job names it, and still runs only on the person's word for that route and its estimate.", + "enum": [ + "never", + "allowed", + null + ] + } + } } }, "$defs": { diff --git a/wai/wai-quantum/schemas/job-result.v1.json b/wai/wai-quantum/schemas/job-result.v1.json index facf3d5ad..73cdb5c52 100644 --- a/wai/wai-quantum/schemas/job-result.v1.json +++ b/wai/wai-quantum/schemas/job-result.v1.json @@ -731,6 +731,24 @@ } } } + }, + "planner": { + "$ref": "#/$defs/planner" + }, + "stopped": { + "type": "object", + "description": "A run stopped at its contract's max_joules by a live reading: it gave no answer, and accuracy.class is none (wai/extensions/quantum-providers.md section 8.7).", + "required": ["at", "joules", "max_joules", "elapsed_ms", "read"], + "properties": { + "at": { "const": "max_joules" }, + "joules": { "type": "number", "description": "What the reading had come to, at or past the ceiling." }, + "max_joules": { "type": "number" }, + "elapsed_ms": { "type": "integer", "minimum": 0 }, + "read": { "type": "string", "description": "What read the run, and what that covers." } + } + }, + "shadow": { + "$ref": "#/$defs/shadow" } }, "$defs": { @@ -760,9 +778,10 @@ "estimate", "heuristic", "measured", - "simulated" + "simulated", + "none" ], - "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance." + "description": "bit-exact: the same bits on every machine; exact: no approximation beyond double-precision rounding; single: single-precision arithmetic; bounded: a rigorous bound beside each value; estimate: a statistical estimate with its standard error; heuristic: an approximation with an estimate of its error, not a bound; measured: counts a processor returned through the person's provider, not reproducible by recomputation; simulated: counts a provider's simulator or emulator returned, measured on no device. Results sealed before simulated existed label a provider's simulator measured, and are read by its provenance. none: the run was stopped at its contract's energy ceiling and gave no answer." }, "approximate": { "const": true, @@ -1549,6 +1568,639 @@ "description": "Beside a registered component: the engine does not certify it." } } + }, + "route_money": { + "description": "What a route costs in money: free, an amount in a currency, or why that is not known. An unknown cost is not free.", + "type": "object", + "required": [ + "free" + ], + "properties": { + "free": { + "type": "boolean" + }, + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "unit": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "at_least": { + "const": true, + "description": "The amount is the least the job can come to: what it takes decides the rest, so it meets no ceiling (cost_at_least)." + } + } + }, + "route_price": { + "description": "What a route costs, with what is really known: a method's memory and work as the planner counts them and its time at the planner's nominal rate; a provider's own estimate, with what that leaves out.", + "type": "object", + "required": [ + "money", + "time", + "memory_bytes", + "work", + "energy", + "leaves_out" + ], + "properties": { + "money": { + "$ref": "#/$defs/route_money" + }, + "time": { + "type": "object", + "required": [ + "seconds" + ], + "properties": { + "seconds": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "basis": { + "enum": [ + "nominal", + "provider" + ] + }, + "why": { + "type": "string" + } + } + }, + "memory_bytes": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "work": { + "type": [ + "number", + "null" + ], + "minimum": 0 + }, + "energy": { + "type": "object", + "required": [ + "joules" + ], + "properties": { + "joules": { + "type": [ + "number", + "null" + ], + "minimum": 0, + "description": "An estimate of what the run takes, from past runs, never a promise. A contract's max_joules is enforced by a live reading while the run goes; an estimate can only refuse a job clearly past a ceiling." + }, + "watch": { + "type": "string", + "description": "What reads the run while it runs, and what that covers: what stops it at a contract's max_joules." + }, + "unwatched": { + "type": "string", + "description": "Why nothing can read the run while it runs; under a ceiling the route is refused (energy_unwatched)." + }, + "basis": { + "type": "string" + }, + "why": { + "type": "string" + } + } + }, + "leaves_out": { + "description": "What this price leaves out: time (it states no time), amount (it states no amount), energy, mitigation (what the provider's own mitigation costs or does), decoder (any decoder's latency), charged (what the provider charges may differ from what it estimates), cancel (its client cannot stop a job it sent).", + "type": "array", + "items": { + "enum": [ + "time", + "amount", + "energy", + "mitigation", + "decoder", + "charged", + "cancel" + ] + } + }, + "program": { + "description": "What the job asks of a provider's device: its shots, and the compiled program's gates and swaps, and its expected success when a calibration states one.", + "type": "object", + "properties": { + "shots": { + "type": "integer", + "minimum": 0 + }, + "native_gates": { + "type": "integer", + "minimum": 0 + }, + "two_qubit_gates": { + "type": "integer", + "minimum": 0 + }, + "swaps": { + "type": "integer", + "minimum": 0 + }, + "expected_success": { + "type": "number" + } + } + } + } + }, + "route": { + "description": "One route the planner could see: its class, its price or why it has none, and what came of it.", + "type": "object", + "required": [ + "route", + "kind", + "class", + "host_dependent", + "price", + "outcome" + ], + "properties": { + "route": { + "type": "string", + "description": "method: or provider:." + }, + "kind": { + "enum": [ + "local", + "provider" + ] + }, + "method": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "device": { + "type": "string" + }, + "provenance": { + "type": "string" + }, + "approximate": { + "const": true + }, + "class": { + "type": "string", + "description": "The accuracy class its result has at worst: a matrix product state's is heuristic, though its result may say exact." + }, + "host_dependent": { + "type": "boolean", + "description": "Whether it depends on the host: a provider's, a method on a GPU, or a registered method." + }, + "auto_rank": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "description": "On a local route: its rank in auto's order for the job's question, or null where auto does not try it; a built-in method's is section 8.7's table." + }, + "price": { + "anyOf": [ + { + "$ref": "#/$defs/route_price" + }, + { + "type": "null" + } + ] + }, + "outcome": { + "enum": [ + "chosen", + "met", + "rejected" + ] + }, + "rejected": { + "type": "object", + "required": [ + "code", + "why" + ], + "properties": { + "code": { + "enum": [ + "not_named", + "fabric", + "class", + "cannot", + "memory", + "providers", + "deadline", + "deadline_unknown", + "cost", + "cost_currency", + "cost_unknown", + "cost_at_least", + "cost_no_ceiling", + "energy", + "energy_unwatched" + ] + }, + "why": { + "type": "string" + } + } + } + } + }, + "planner": { + "description": "Why this route ran (wai.quantum.planner/1): every route the host could see, each one's price or reason for rejection, and the choice. Sealed by the receipt; a verifier recomputes each route's outcome and the choice from what it states (wai/extensions/quantum-providers.md section 8.7). A plan carries it too, with the refusal in place of the choice when no route meets the contract.", + "type": "object", + "required": [ + "format", + "wanted", + "wanted_from", + "auto", + "host", + "routes", + "choice", + "why", + "stable", + "named", + "question" + ], + "properties": { + "format": { + "const": "wai.quantum.planner/1" + }, + "wanted": { + "type": [ + "string", + "null" + ], + "description": "The class wanted: the contract's, else that of the route the job names or auto's pick." + }, + "wanted_from": { + "enum": [ + "contract", + "named", + "auto", + null + ] + }, + "named": { + "type": [ + "string", + "null" + ], + "description": "The route the job names: the provider or the method its request names, or the one method a device target's job runs on; null when it names none." + }, + "question": { + "enum": [ + "noise", + "counts", + "expectations", + "amplitudes" + ], + "description": "The question the job asks, read from its request, which orders the methods auto tries (section 8.7)." + }, + "auto": { + "type": [ + "string", + "null" + ], + "description": "The route auto picks, when the job leaves the method to it." + }, + "host": { + "type": "object", + "required": [ + "job_bytes", + "providers" + ], + "properties": { + "job_bytes": { + "type": "number", + "minimum": 0 + }, + "providers": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "routes": { + "type": "array", + "items": { + "$ref": "#/$defs/route" + } + }, + "choice": { + "type": [ + "string", + "null" + ] + }, + "why": { + "type": "string" + }, + "refusal": { + "description": "When no route meets the contract, in a plan: the refusal as data.", + "type": "object" + }, + "stable": { + "type": "object", + "required": [ + "scope", + "routes", + "digest", + "choice" + ], + "properties": { + "scope": { + "type": "string" + }, + "routes": { + "type": "array", + "items": { + "type": "string" + } + }, + "digest": { + "type": "string" + }, + "choice": { + "type": "boolean" + } + } + }, + "shadow": { + "description": "The classical method that would shadow a provider's answer within the contract, or why none can.", + "type": "object", + "required": [ + "route" + ], + "properties": { + "route": { + "type": [ + "string", + "null" + ] + }, + "class": { + "type": "string" + }, + "request": { + "type": "object" + }, + "budget_seconds": { + "type": "number", + "minimum": 0 + }, + "price": { + "$ref": "#/$defs/route_price" + }, + "code": { + "enum": [ + "budget", + "memory", + "none" + ] + }, + "why": { + "type": "string" + }, + "tried": { + "type": "array", + "items": { + "type": "object", + "properties": { + "route": { + "type": "string" + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + } + } + }, + "kept": { + "description": "What the contract asked, against what happened; each kept is null when it cannot be said. A result that missed one is sealed and says so.", + "type": "object", + "properties": { + "deadline": { + "type": "object", + "required": [ + "seconds", + "elapsed_ms", + "kept" + ], + "properties": { + "seconds": { + "type": "number" + }, + "elapsed_ms": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "energy": { + "type": "object", + "required": [ + "max_joules", + "joules", + "kept" + ], + "properties": { + "max_joules": { + "type": "number" + }, + "joules": { + "type": [ + "number", + "null" + ] + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + }, + "cost": { + "type": "object", + "required": [ + "max_cost", + "charged", + "kept" + ], + "properties": { + "max_cost": { + "type": "object", + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "charged": { + "type": [ + "object", + "null" + ], + "properties": { + "amount": { + "type": "string" + }, + "currency": { + "type": "string" + } + } + }, + "kept": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } + }, + "shadow": { + "description": "A classical method's answer beside a provider's, and their distance, for a contract job a provider answered; or why there is none. Its request can be run again by anyone, to the same counts.", + "type": "object", + "required": [ + "ran" + ], + "properties": { + "ran": { + "type": "boolean" + }, + "route": { + "type": "string" + }, + "accuracy": { + "$ref": "#/$defs/accuracy" + }, + "request": { + "type": "object", + "properties": { + "qasm": { + "type": "string" + }, + "shots": { + "type": "integer" + }, + "seed": { + "type": "integer" + }, + "method": { + "type": "string" + } + } + }, + "shots": { + "type": "integer", + "minimum": 1 + }, + "counts": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 1 + } + }, + "distinct_outcomes": { + "type": "integer", + "minimum": 0 + }, + "omitted_shots": { + "type": "integer", + "minimum": 0 + }, + "distance": { + "type": "object", + "required": [ + "computed" + ], + "properties": { + "computed": { + "type": "boolean" + }, + "numerator": { + "type": "integer", + "minimum": 0 + }, + "denominator": { + "type": "integer", + "minimum": 1 + }, + "total_variation": { + "type": "number", + "minimum": 0, + "maximum": 1 + }, + "hellinger_fidelity": { + "type": "number" + }, + "sampling_tvd_bound": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "A bound on the total variation the shots alone leave between two samples of one distribution, on average (section 8.7): each outcome's pooled count split as a fair coin splits it." + }, + "why": { + "type": "string" + } + } + }, + "elapsed_ms": { + "type": "integer", + "minimum": 0 + }, + "code": { + "type": "string" + }, + "why": { + "type": "string" + } + } } } } diff --git a/wai/wai-quantum/schemas/plan.v1.json b/wai/wai-quantum/schemas/plan.v1.json index 4642b5a8d..b7edc4e06 100644 --- a/wai/wai-quantum/schemas/plan.v1.json +++ b/wai/wai-quantum/schemas/plan.v1.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://git.transaction.science/Transaction-Science/open-standards/raw/branch/main/wai/wai-quantum/schemas/plan.v1.json", "title": "wai.quantum.plan/1", - "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it.", + "description": "What a job will run, before it runs: the method the planner chose and why, the memory the job is admitted with (an upper estimate) and its work in the method's own unit. The command line's plan --json and both servers' plan tools give it. A job with a contract carries the planner's reasoning.", "type": "object", "required": [ "method", @@ -34,6 +34,9 @@ "target": { "$ref": "job-result.v1.json#/$defs/target_placement" }, + "planner": { + "$ref": "job-result.v1.json#/$defs/planner" + }, "metered": { "type": "boolean", "description": "True when a job naming method mps would pass one job's work at the bond it asks for: it runs under a meter of the bonds it reaches, may take far less than `work`, and stops with J011 if it passes `work`." diff --git a/wai/wai-quantum/src/engine/catalog.rs b/wai/wai-quantum/src/engine/catalog.rs index 5d2cf4dc8..8f83cc459 100644 --- a/wai/wai-quantum/src/engine/catalog.rs +++ b/wai/wai-quantum/src/engine/catalog.rs @@ -1255,8 +1255,22 @@ pub(crate) fn reads_own<'a>(reg: &'a Registry, v: &Value) -> Option<&'a dyn Meth v.get("method").and_then(Value::as_str).and_then(|n| reg.method(n)).filter(|m| m.reads_program()) } -/// [`plan`] through `reg`: its methods, channels and passes. +/// [`plan`] through `reg`: its methods, channels and passes. A job with a +/// `contract` is the planner's ([`super::planner`]); one with none plans as it +/// always has, byte for byte. pub(crate) fn plan_in(reg: &Registry, v: &Value, job_bytes: u64) -> Result { + if v.get("contract").is_some_and(|c| !c.is_null()) { + #[cfg(feature = "quantum_receipt")] + return super::planner::plan_in(reg, v, job_bytes); + #[cfg(not(feature = "quantum_receipt"))] + return Err(tag(refusal::CONTRACT_HERE, "this build has no planner under a contract (the engine's quantum_receipt feature)")); + } + plan_plain(reg, v, job_bytes) +} + +/// The plan of a job taken without its contract, as `auto` or the method it +/// names gives it. +pub(crate) fn plan_plain(reg: &Registry, v: &Value, job_bytes: u64) -> Result { if let Some(m) = reads_own(reg, v) { return m.plan(&Job::new(reg, v, job_bytes, None, &[])); } @@ -1292,7 +1306,7 @@ pub(crate) fn plan_in(reg: &Registry, v: &Value, job_bytes: u64) -> Result) -> Result { +pub(crate) fn choose_placed(job: &Job<'_>) -> Result { use super::fabric::Ask; let r = job.as_read()?; let ask = super::fabric::asked(job.json())?; @@ -1306,13 +1320,18 @@ fn choose_placed(job: &Job<'_>) -> Result { /// `p` for the job `v`, read as `r`, admitting the memory its intents' check /// takes beside the run, where it fits (super::verdict). fn with_intent(reg: &Registry, v: &Value, r: &Request, mut p: Plan, job_bytes: u64) -> Result { - if let Some(i) = v.get("intent").filter(|i| !i.is_null()) { - let need = super::verdict::intent_memory_in(reg, v, &super::verdict::intents(i)?, r.program.n_qubits, r.noise.is_some(), job_bytes); - p.memory_bytes = p.memory_bytes.max(need); - } + p.memory_bytes = p.memory_bytes.max(intent_need(reg, v, r, job_bytes)?); Ok(p) } +/// The memory the job's intents' check takes beside the run, where it fits. +pub(crate) fn intent_need(reg: &Registry, v: &Value, r: &Request, job_bytes: u64) -> Result { + match v.get("intent").filter(|i| !i.is_null()) { + Some(i) => Ok(super::verdict::intent_memory_in(reg, v, &super::verdict::intents(i)?, r.program.n_qubits, r.noise.is_some(), job_bytes)), + None => Ok(0), + } +} + /// The method `m`'s plan for `job`: refused for a method that models no /// noise when the job has a noise model, then the method's own plan, then /// every channel the job names held to what the method takes (each refusal diff --git a/wai/wai-quantum/src/engine/energy.rs b/wai/wai-quantum/src/engine/energy.rs index 0446f7ea6..494dd8a9d 100644 --- a/wai/wai-quantum/src/engine/energy.rs +++ b/wai/wai-quantum/src/engine/energy.rs @@ -49,6 +49,227 @@ use serde_json::{Value, json}; +// --------------------------------------------------------------------------- +// What a host estimates of a run before it runs +// --------------------------------------------------------------------------- + +/// One timed run of a method on a host: its work as the planner counts it, the +/// time the engine took over it, and the power over it where a reading gave +/// one, with the time that power was read over. A host keeps these to estimate +/// its next runs from ([`estimate`]): the job service from the figures it seals, +/// the command line from the readings it takes around its own runs. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Timing { + pub work: u64, + pub elapsed_ms: u64, + /// Watts over the run, where it was read. + pub watts: Option, + /// The microseconds `watts` was read over: the whole of what the reading + /// covers, which can be longer than `elapsed_ms`. + pub window_us: Option, + /// The reading leaves out a device the run used. + pub partial: bool, +} + +/// The timings a host keeps of one method, at most. +pub const TIMINGS: usize = 32; + +/// What a host estimates of a plan before it runs, as a dry run states it: its +/// time and its energy. Always an estimate from past runs, never a reading of +/// this one, and it promises nothing ([`Held`]): its provenance class is +/// `Estimator`. +#[derive(Clone, Debug, PartialEq)] +pub struct Estimate { + pub time: Value, + pub energy: Value, +} + +/// What a host says of a route's energy before it runs (engine::planner). A +/// contract's `max_joules` is enforced while the run goes, by a live reading that +/// stops it at the ceiling: no figure before a run can promise it, since a job's +/// work leaves out what drives its time, and the same job read twice differs. +#[derive(Clone, Debug, PartialEq)] +pub struct Held { + /// An estimate, never a bound: its joules and what they rest on, or why there + /// is none. It can refuse a job clearly past a ceiling, and promises nothing. + pub estimate: Result<(f64, String), String>, + /// What reads the run while it runs and what that covers, or why nothing can. + /// Under a ceiling a route with no reading is refused. + pub watch: Result, +} + +/// How often a run under a ceiling is read, in milliseconds. +pub const WATCH_MS: u64 = 10; + +/// How long a run under a ceiling may go unread, in milliseconds. A counter can lag +/// a read, but a ceiling nothing reads is held by nothing, so a run past this is +/// stopped. Time, not a count of reads: a watcher the host schedules late still +/// loses the run after a second. +pub const WATCH_LOST_MS: u64 = 1000; + +/// What a live reading of a run came to. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Watched { + /// It reached the ceiling, at this many joules. + Reached(f64), + /// The counter stopped reading. + Lost, +} + +/// The least power, in watts (nanojoules a nanosecond), an exited process's read +/// must show over its CPU time to be a reading of it at all. +pub const EXITED_FLOOR_W: f64 = 0.05; + +/// A run under a ceiling, read by read: what ends it, and the longest time the +/// host let pass between two reads (from the start of the watch), which is what +/// the ceiling is held to. A counter that keeps one value while the run spends CPU +/// time is frozen, not live: a second of that loses the run, as silence does. +#[derive(Debug)] +pub struct Watcher { + ceiling: f64, + read_at: std::time::Instant, + taken_at: std::time::Instant, + last: Option<(f64, Option)>, + /// The longest time between two reads so far, the first counted from the start. + pub longest_gap: std::time::Duration, +} + +impl Watcher { + pub fn new(ceiling: f64) -> Watcher { + Watcher::new_at(ceiling, std::time::Instant::now()) + } + + pub fn new_at(ceiling: f64, at: std::time::Instant) -> Watcher { + Watcher { ceiling, read_at: at, taken_at: at, last: None, longest_gap: std::time::Duration::ZERO } + } + + /// One read now, or one that did not read: what ends the run, where it does. + pub fn take(&mut self, read: Option) -> Option { + self.take_at(read, None, std::time::Instant::now()) + } + + /// [`Watcher::take`], with the run's CPU time so far where it is known. + pub fn take_with(&mut self, read: Option, cpu_ns: Option) -> Option { + self.take_at(read, cpu_ns, std::time::Instant::now()) + } + + /// A read at `at`, with the run's CPU time then where it is known: a reading + /// counts as live only when it moved, or when the run spent no CPU time since. + pub fn take_at(&mut self, read: Option, cpu_ns: Option, at: std::time::Instant) -> Option { + self.longest_gap = self.longest_gap.max(at.saturating_duration_since(self.taken_at)); + self.taken_at = at; + let lost = |w: &Watcher| (at.saturating_duration_since(w.read_at) >= std::time::Duration::from_millis(WATCH_LOST_MS)).then_some(Watched::Lost); + match read { + Some(j) if j >= self.ceiling => Some(Watched::Reached(j)), + Some(j) => { + let moved = match self.last { + None => true, + Some((before, cpu_before)) => j != before || matches!((cpu_before, cpu_ns), (Some(b), Some(a)) if a <= b), + }; + self.last = Some((j, cpu_ns)); + if moved { + self.read_at = at; + None + } else { + lost(self) + } + } + None => lost(self), + } + } + + /// Whether `joules`, read at the run's end with its CPU time then, stands where + /// the last live read stood though the run spent at least a millisecond of CPU + /// time since: the frozen rule applied to an exited read. A run that only waited + /// and exited after its last live read spent less, and its read stands honestly. + pub fn stood_still(&self, joules: f64, cpu_ns: Option) -> bool { + match self.last { + Some((before, Some(b))) => joules == before && cpu_ns.is_some_and(|a| a >= b.saturating_add(1_000_000)), + Some((before, None)) => joules == before && cpu_ns.is_none(), + None => false, + } + } + + /// What the reads were, as a stopped run's receipt says it. + pub fn said(&self, what: &str) -> String { + format!("{what}; the longest time between two reads was {} ms", self.longest_gap.as_millis()) + } +} + +/// The middle of the positive, finite values among `v`, once there are three. +fn median(mut v: Vec) -> Option { + v.retain(|x| x.is_finite() && *x > 0.0); + if v.len() < 3 { + return None; + } + v.sort_by(f64::total_cmp); + Some(v[v.len() / 2]) +} + +/// `plan`'s time and energy before it runs, from `timed`, what `host` (`this +/// service`, `this command line`) timed of the plan's method here: its median +/// rate once three runs are timed, else the planner's nominal rate; and its +/// median power over that time once three runs were metered. `unmetered` is why +/// the host meters nothing, where it does not; `at_most_s` bounds a run whose +/// time is not known. One implementation for every host that estimates. +pub fn estimate(plan: &super::catalog::Plan, timed: &[Timing], host: &str, unmetered: Option<&str>, at_most_s: u64) -> Estimate { + let method = plan.method.as_str(); + let rates: Vec = timed.iter().filter(|x| x.elapsed_ms >= 5 && x.work > 0).map(|x| x.work as f64 / (x.elapsed_ms as f64 / 1e3)).collect(); + let n = rates.len(); + let (seconds, basis) = match (median(rates), super::catalog::nominal_rate(method)) { + (Some(rate), _) => (Some(plan.work as f64 / rate), format!("the median rate of the last {n} {method} jobs {host} timed")), + (None, Some(rate)) => (Some(plan.work as f64 / rate), format!("the planner's nominal rate for {method} ({rate:.1e} of its work units a second); {host} has not yet timed three of its jobs")), + (None, None) => (None, format!("the work the planner counts for {method} does not predict its time, and {host} has not yet timed three of its jobs")), + }; + let time = match seconds { + Some(s) => json!({ "seconds": s, "basis": basis, "note": "an estimate: the run is bounded by the job's time limit, not by this" }), + None => json!({ "seconds": null, "why": basis, "at_most": at_most_s }), + }; + let powers: Vec = timed.iter().filter_map(|x| x.watts).collect(); + let k = powers.len(); + let energy = match (median(powers), seconds) { + (Some(w), Some(s)) if (w * s * 1e6).round() < 1.0 => json!({ "unestimated": "the estimate is under a microjoule, below what a figure resolves" }), + (Some(w), Some(s)) => json!({ + "joules_micro_estimate": (w * s * 1e6).round() as u64, + "energy_provenance": "Estimator", + "basis": format!("the median power of the last {k} metered {method} jobs here, over the estimated time"), + "note": "an estimate from past readings, never a reading of this job", + }), + _ => json!({ "unestimated": match unmetered { + Some(why) => format!("this host does not meter jobs ({why}), so there is nothing to estimate from"), + None if seconds.is_none() => "no time estimate to take the power over".to_string(), + None => format!("{host} has not yet metered three {method} jobs to estimate from"), + } }), + }; + Estimate { time, energy } +} + +/// This machine's name, as the operating system gives it: what keeps readings +/// taken on one machine from bounding runs on another that shares a home. Empty +/// where there is none. +#[cfg(unix)] +pub fn machine() -> String { + unsafe extern "C" { + fn gethostname(name: *mut std::ffi::c_char, len: usize) -> std::ffi::c_int; + } + let mut buf = [0u8; 256]; + // SAFETY: `buf` is valid for its length, and the last byte is left for the end. + let ok = unsafe { gethostname(buf.as_mut_ptr().cast(), buf.len() - 1) } == 0; + let end = buf.iter().position(|b| *b == 0).unwrap_or(buf.len()); + let name = if ok { String::from_utf8_lossy(&buf[..end]).into_owned() } else { String::new() }; + // Two machines can share a name (a cloned VM, a fixed container hostname). + match std::fs::read_to_string("/etc/machine-id") { + Ok(id) if !id.trim().is_empty() => format!("{name} {}", id.trim()), + _ => name, + } +} + +/// [`machine`], where the operating system gives no name this reads. +#[cfg(not(unix))] +pub fn machine() -> String { + String::new() +} + /// The least `joules_micro × relative_ppm` a hardware class may declare /// (energy-measurement §2.3): `⌈10⁶ × 0.5/√3⌉`. pub const RESOLUTION_FLOOR_UJ_PPM: u64 = 288_676; @@ -88,6 +309,12 @@ pub fn figure(reading: Option<&Reading>, gpu: bool, unmetered_why: &str) -> Valu // here; that is no reading, not a reading of zero. return json!({ "unmetered": "the worker's energy counter did not advance: it is not live on this host" }); } + // An exited process read far below what its CPU time implies (under 50 mW over + // it) missed its last stretch on a core: on Apple silicon a thread's energy is + // added when it leaves a core, and one that exits on it leaves that out. + if (r.energy_nj as f64) < r.cpu_ns as f64 * EXITED_FLOOR_W { + return json!({ "unmetered": "the worker's counter read far below what its CPU time implies: the read missed its last stretch on a core, so it is no reading" }); + } let total_nj = r.energy_nj.saturating_add(r.billed_nj).saturating_sub(r.serviced_nj); let joules_micro = total_nj.saturating_add(500) / 1000; if joules_micro == 0 { @@ -287,6 +514,17 @@ fn zone_delta(before: u64, after: u64, range: Option) -> Option { range?.checked_sub(before)?.checked_add(after) } +/// What no package draws, in watts: at this, the time a counter takes to wrap +/// is the least it can be. +pub const WRAP_WATTS: f64 = 1000.0; + +/// The longest a reading of counters that wrap at `ranges` (microjoules) can be +/// trusted: past it one may have wrapped more than once, which two reads cannot +/// see. None where a range is not known. +pub fn wrap_seconds(ranges: &[Option]) -> Option { + ranges.iter().try_fold(f64::INFINITY, |least, r| r.map(|r| least.min(r as f64 / 1e6 / WRAP_WATTS))) +} + /// What the probe found of a live counter. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Probe { @@ -388,6 +626,13 @@ impl Packages { Self::open_in(std::path::Path::new("/sys/class/powercap")) } + /// The packages at `root` taken to update as `probe` says, with no probe of + /// their own: for a counter that a test drives. + pub fn open_with_probe(root: &std::path::Path, probe: Probe) -> Result { + let zones = zones_in(root, &|p| std::fs::read_to_string(p)).map_err(|a| a.why().to_string())?; + Ok(Packages { zones, probe }) + } + /// [`Packages::open`] on the tree at `root`. pub fn open_in(root: &std::path::Path) -> Result { let zones = zones_in(root, &|p| std::fs::read_to_string(p)).map_err(|a| a.why().to_string())?; @@ -403,6 +648,63 @@ impl Packages { Some(PackageSnapshot { uj, at: std::time::Instant::now() }) } + /// What the packages have taken since `before`, read by read: added up as it + /// goes, so that a counter that wraps during a long run loses nothing. + pub fn since(&self, before: PackageSnapshot) -> impl FnMut() -> Option + Send + '_ { + let mut added = Accumulated::new(self, before); + move || added.read() + } +} + +/// The packages' energy since a first read, added up read by read, each read's step +/// corrected for a wrap: what a run took in all, however many ranges it passes, so +/// long as no two reads are a wrap apart. +#[derive(Debug)] +pub struct Accumulated<'a> { + packages: &'a Packages, + first: PackageSnapshot, + last: PackageSnapshot, + total_uj: u64, +} + +impl<'a> Accumulated<'a> { + pub fn new(packages: &'a Packages, first: PackageSnapshot) -> Accumulated<'a> { + Accumulated { packages, last: first.clone(), first, total_uj: 0 } + } + + /// A read now, its step added: the total so far in joules, or none where a + /// package did not read. + pub fn read(&mut self) -> Option { + let now = self.packages.read()?; + self.total_uj = self.total_uj.saturating_add(self.packages.between(&self.last, &now, 0)?.energy_uj); + self.last = now; + Some(self.total_uj as f64 / 1e6) + } + + /// What was added up, as one reading from the first read to the last, with + /// `concurrent` other jobs on the host. + pub fn reading(&self, concurrent: u64) -> PackageReading { + let mut r = self.packages.between(&self.first, &self.first, concurrent).unwrap_or(PackageReading { + energy_uj: 0, + window_ns: 0, + packages: self.packages.zones.len() as u32, + update_ns: self.packages.probe.update_ns, + step_uj: self.packages.probe.step_uj, + concurrent, + }); + r.energy_uj = self.total_uj; + r.window_ns = self.last.at.saturating_duration_since(self.first.at).as_nanos() as u64; + r + } +} + +impl Packages { + + /// The longest a reading between two reads can be trusted ([`wrap_seconds`]). + pub fn wrap_seconds(&self) -> Option { + wrap_seconds(&self.zones.iter().map(|z| z.range).collect::>()) + } + /// The reading from `before` to `after`, with `concurrent` other jobs on /// the host; none if a package's delta is unknown. pub fn between(&self, before: &PackageSnapshot, after: &PackageSnapshot, concurrent: u64) -> Option { @@ -613,12 +915,13 @@ mod tests { const WHY: &str = "this host has no per-process energy counter"; fn reading(energy_nj: u64) -> Reading { - Reading { energy_nj, billed_nj: 0, serviced_nj: 0, cpu_ns: 250_000_000, window_ns: 300_000_000 } + // CPU time short enough that no size here is below the exited-read floor. + Reading { energy_nj, billed_nj: 0, serviced_nj: 0, cpu_ns: 1_000, window_ns: 300_000_000 } } #[test] fn a_figure_is_a_counter_reading_with_its_declared_uncertainty() { - let f = figure(Some(&reading(812_345_678)), false, WHY); + let f = figure(Some(&Reading { cpu_ns: 250_000_000, ..reading(812_345_678) }), false, WHY); assert_eq!(f["joules_micro"], 812_346); assert_eq!(f["energy_provenance"], "OnChipCounter"); assert_eq!(f["energy_counter_filtering"], "Unknown"); @@ -824,4 +1127,130 @@ mod tests { assert!(after.energy_nj > before.energy_nj, "{before:?} {after:?}"); assert!(after.cpu_ns > before.cpu_ns && after.window_ns >= before.window_ns); } + + fn plan(method: &str, work: u64) -> super::super::catalog::Plan { + super::super::catalog::Plan { method: method.into(), why: String::new(), memory_bytes: 1, work, qubits: 2, target: None, metered: false } + } + + /// One estimate for every host: its words name whose runs it rests on, and they + /// are the job service's, word for word; three metered runs give one labelled + /// an estimate, fewer give none with why, and one under a microjoule is none. + #[test] + fn a_host_s_estimate_rests_on_its_own_runs_and_says_whose() { + let p = plan("stabilizer", 2_000_000); + let run = |watts| Timing { work: 1_000_000, elapsed_ms: 100, watts, window_us: Some(100_000), partial: false }; + let none = estimate(&p, &[], "this command line", None, 5); + assert!(none.time["basis"].as_str().unwrap().contains("this command line has not yet timed three"), "{}", none.time); + assert_eq!(none.energy["unestimated"], "this command line has not yet metered three stabilizer jobs to estimate from"); + let unmetered = estimate(&p, &[run(None), run(None), run(None)], "this service", Some("no counter"), 5); + assert_eq!(unmetered.energy["unestimated"], "this host does not meter jobs (no counter), so there is nothing to estimate from"); + assert!(unmetered.time["basis"].as_str().unwrap().contains("this service timed"), "{}", unmetered.time); + // 2e6 work at 1e7 a second, 0.2 s at 10 W: 2 J, whatever the host meters now. + let three = estimate(&p, &[run(Some(10.0)), run(Some(10.0)), run(Some(10.0))], "this service", Some("no counter"), 5); + assert_eq!(three.energy["joules_micro_estimate"], 2_000_000); + assert_eq!(three.energy["energy_provenance"], "Estimator"); + assert_eq!(three.energy["basis"], "the median power of the last 3 metered stabilizer jobs here, over the estimated time"); + assert_eq!(three.energy["note"], "an estimate from past readings, never a reading of this job"); + // A tiny job: under half a microjoule there is no figure. + // 1 work unit at 1e7 a second is 0.1 µs; at 0.1 W, 0.01 µJ. + let tiny = estimate(&plan("stabilizer", 1), &[run(Some(0.1)), run(Some(0.1)), run(Some(0.1))], "this service", None, 5); + assert_eq!(tiny.energy["unestimated"], "the estimate is under a microjoule, below what a figure resolves"); + // A method whose time is not predicted has no energy to take over it. + let pauli = estimate(&plan("pauli", 10), &[run(Some(10.0)), run(Some(10.0))], "this service", None, 5); + assert_eq!((pauli.time["at_most"].as_u64(), pauli.energy["unestimated"].as_str()), (Some(5), Some("no time estimate to take the power over"))); + } + + /// A run is stopped by the first reading at or past its ceiling. A read that + /// fails is passed over, as a counter's lag is; a counter silent for a second + /// of time loses the run its ceiling, however few reads the host allowed in it, + /// and so does one that keeps one value while the run spends CPU time. The + /// longest time between two reads is kept, the first counted from the start. + #[test] + fn a_live_reading_stops_at_the_ceiling_and_a_silent_second_loses_it() { + use std::time::{Duration, Instant}; + let t0 = Instant::now(); + let ms = |n: u64| t0 + Duration::from_millis(n); + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(Some(0.5), None, ms(40)), None); + assert_eq!(w.longest_gap, Duration::from_millis(40), "the time before the first read is a gap"); + assert_eq!(w.take_at(None, None, ms(50)), None); + assert_eq!(w.take_at(Some(1.5), None, ms(280)), None); + assert_eq!(w.take_at(Some(2.0), None, ms(290)), Some(Watched::Reached(2.0)), "at the ceiling, not only past it"); + assert_eq!(w.longest_gap, Duration::from_millis(230)); + assert!(w.said("a counter").ends_with("the longest time between two reads was 230 ms")); + // Silent: two late reads a second apart lose it. + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(Some(1.0), None, ms(10)), None); + assert_eq!(w.take_at(None, None, ms(500)), None); + assert_eq!(w.take_at(None, None, ms(1010)), Some(Watched::Lost)); + // A read that moved keeps it. + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(None, None, ms(900)), None); + assert_eq!(w.take_at(Some(1.0), None, ms(950)), None); + assert_eq!(w.take_at(None, None, ms(1900)), None); + assert_eq!(w.take_at(None, None, ms(1950)), Some(Watched::Lost)); + // Frozen: one value for a second while the run spends CPU time is no reading. + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(Some(1.0), Some(10), ms(10)), None); + assert_eq!(w.take_at(Some(1.0), Some(500_000_000), ms(500)), None); + assert_eq!(w.take_at(Some(1.0), Some(1_000_000_000), ms(1010)), Some(Watched::Lost)); + // An exited read where the last live read stood, the run having spent CPU + // time since, stood still too; one with no CPU time spent did not. + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(Some(0.3), Some(10), ms(10)), None); + assert!(w.stood_still(0.3, Some(900_000_000)) && !w.stood_still(0.4, Some(900_000_000)) && !w.stood_still(0.3, Some(10))); + assert!(!w.stood_still(0.3, Some(500_010)), "a run that only waited and exited spent under a millisecond"); + // One value while the run spends none is a run waiting, not a frozen counter. + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(Some(1.0), Some(10), ms(10)), None); + assert_eq!(w.take_at(Some(1.0), Some(10), ms(1500)), None); + // A package counter, whose CPU time is not known, that stops moving is frozen. + let mut w = Watcher::new_at(2.0, t0); + assert_eq!(w.take_at(Some(1.0), None, ms(10)), None); + assert_eq!(w.take_at(Some(1.0), None, ms(1010)), Some(Watched::Lost)); + } + + /// An exited read far below what its CPU time implies missed its last stretch + /// on a core, and is no reading; one in proportion is. + #[test] + fn an_exited_read_far_below_its_cpu_time_is_no_reading() { + let r = |energy_nj: u64, cpu_ns: u64| Reading { energy_nj, billed_nj: 0, serviced_nj: 0, cpu_ns, window_ns: cpu_ns }; + assert!(figure(Some(&r(7_094, 4_500_000)), false, "x")["unmetered"].as_str().unwrap().contains("last stretch on a core")); + assert!(figure(Some(&r(3_000_000, 4_500_000)), false, "x")["joules_micro"].is_number()); + } + + /// Added up read by read, a package counter's steps make what the run took in + /// all though the counter wraps twice: one delta from first to last loses each + /// whole range. + #[test] + fn a_package_counter_added_up_read_by_read_keeps_every_range() { + let d = std::env::temp_dir().join(format!("wai-energy-ranges-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&d); + let zone = d.join("intel-rapl:0"); + std::fs::create_dir_all(&zone).unwrap(); + std::fs::write(zone.join("name"), "package-0\n").unwrap(); + std::fs::write(zone.join("max_energy_range_uj"), "1000\n").unwrap(); + let file = zone.join("energy_uj"); + std::fs::write(&file, "0\n").unwrap(); + let zones = zones_in(&d, &|p| std::fs::read_to_string(p)).unwrap(); + let p = Packages { zones, probe: Probe { update_ns: 1_000_000, step_uj: 1 } }; + let mut added = Accumulated::new(&p, p.read().unwrap()); + let first = p.read().unwrap(); + // 400 µJ a read, ten reads: 4000 µJ, four times the range. + for k in 1..=10u64 { + std::fs::write(&file, format!("{}\n", (k * 400) % 1000)).unwrap(); + added.read().unwrap(); + } + assert_eq!(added.reading(0).energy_uj, 4000); + assert!(p.between(&first, &p.read().unwrap(), 0).unwrap().energy_uj < 1000, "one delta keeps less than a range"); + let _ = std::fs::remove_dir_all(&d); + } + + /// A reading past the time a counter can wrap twice is not to be trusted: at the + /// most any package draws, a 65.5 kJ range is 65.5 s, and the least range rules. + #[test] + fn a_counter_s_reading_is_trusted_only_within_one_wrap() { + assert_eq!(wrap_seconds(&[Some(65_532_610_987), Some(262_143_328_850)]), Some(65.532610987)); + assert_eq!(wrap_seconds(&[Some(65_532_610_987), None]), None, "a range not known rules nothing out"); + } } diff --git a/wai/wai-quantum/src/engine/guide.rs b/wai/wai-quantum/src/engine/guide.rs index 4a35b2719..af15832c2 100644 --- a/wai/wai-quantum/src/engine/guide.rs +++ b/wai/wai-quantum/src/engine/guide.rs @@ -84,7 +84,7 @@ pub fn instructions() -> String { } /// What a receipt shows, and what it does not. -pub const RECEIPTS: &str = "Every result carries an Ed25519 signature over the BLAKE3 digest of the RFC 8785 canonical text of the request and of the result without its receipt. The job service signs with the key `GET /v1` publishes; the command line signs with the user's own key (`wai-quantum key` prints its did:key). `wai-quantum verify` checks either offline, and a result still verifies after any JSON reader has carried it. A receipt shows that the key signed this request and this result, and anyone can rerun the request to compare; it does not show who holds the key, nor that the physics is right. A result's `energy` is the CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or `unmetered` with the reason (the command line does not meter a run)."; +pub const RECEIPTS: &str = "Every result carries an Ed25519 signature over the BLAKE3 digest of the RFC 8785 canonical text of the request and of the result without its receipt. The job service signs with the key `GET /v1` publishes; the command line signs with the user's own key (`wai-quantum key` prints its did:key). `wai-quantum verify` checks either offline, and a result still verifies after any JSON reader has carried it. A receipt shows that the key signed this request and this result, and anyone can rerun the request to compare; it does not show who holds the key, nor that the physics is right. A result's `energy` is the CPU energy of the job's process as the kernel counts it, with its uncertainty and what it leaves out, or `unmetered` with the reason (the command line seals no reading of a run: it reads some runs only to bound later ones)."; /// The resources both servers list. pub const LANGUAGE: &str = "wai-quantum://docs/language"; diff --git a/wai/wai-quantum/src/engine/job.rs b/wai/wai-quantum/src/engine/job.rs index 8cf2fdb37..9907f4ee2 100644 --- a/wai/wai-quantum/src/engine/job.rs +++ b/wai/wai-quantum/src/engine/job.rs @@ -12,7 +12,13 @@ use serde_json::{Value, json}; /// `energy` (the host's figure, or why it has none) inside the result, and /// the result sealed with `key`. pub fn run(request: &Value, job_bytes: u64, key: &SigningKey, energy: Value) -> Result { - let (plan, result) = plan_and_run(request, job_bytes)?; + run_with(request, job_bytes, key, energy, None) +} + +/// [`run`], on a host with its word on a plan's energy (`joules`, +/// engine::energy::Held): what it estimates, and what would read the run. +pub fn run_with(request: &Value, job_bytes: u64, key: &SigningKey, energy: Value, joules: Option<&super::planner::Joules<'_>>) -> Result { + let (plan, result) = plan_and_run_with(request, job_bytes, joules)?; Ok(seal(request, &plan, result, key, energy)) } @@ -20,7 +26,20 @@ pub fn run(request: &Value, job_bytes: u64, key: &SigningKey, energy: Value) -> /// not yet sealed. A host that runs a job in a process of its own, away from /// its key, gives these back to be sealed ([`seal`]). pub fn plan_and_run(request: &Value, job_bytes: u64) -> Result<(catalog::Plan, Value), String> { + plan_and_run_with(request, job_bytes, None) +} + +/// [`plan_and_run`], with the host's word on a plan's energy where it has one. +pub fn plan_and_run_with(request: &Value, job_bytes: u64, joules: Option<&super::planner::Joules<'_>>) -> Result<(catalog::Plan, Value), String> { exact_request(request)?; + // A contract's reasoning travels with its result (engine::planner). + if super::planner::has_contract(request) { + let mut host = super::planner::Host::new(job_bytes); + if let Some(j) = joules { + host = host.with_joules(j); + } + return super::planner::plan_and_run_in(super::registry::Registry::builtins(), request, &host); + } let plan = catalog::plan(request, job_bytes)?; let result = super::run::run(request, &plan)?; Ok((plan, result)) @@ -53,6 +72,7 @@ pub fn exact_request(request: &Value) -> Result<(), String> { /// form: `energy` inside the result, and the result sealed with `key`. pub fn seal(request: &Value, plan: &catalog::Plan, mut result: Value, key: &SigningKey, energy: Value) -> Value { result["energy"] = energy; + super::planner::finish(request, &mut result, None); receipt::seal_into(key, request, &mut result); json!({ "status": "done", @@ -162,6 +182,9 @@ pub struct Check { /// to state it: the class, whether its fields are stated, its counts' /// source and how the device was asked to run the program. pub provider: Option, + /// For a contract job, what its reasoning says (§8.7): the route chosen, + /// the class wanted and given, what was kept, and the shadow. + pub planner: Option, } impl Check { @@ -178,6 +201,9 @@ impl Check { if let Some(p) = &self.provider { v["provider"] = p.clone(); } + if let Some(p) = &self.planner { + v["planner"] = p.clone(); + } v } @@ -298,6 +324,7 @@ pub fn check(job: &Value) -> Check { // Nothing to check it against, but the result still says what it is. let mut c = Check::only(NO_RECEIPT); c.provider = super::provider::check(request, result).1; + c.planner = super::planner::statement(result); return c; }; let set = is_set(job); @@ -447,6 +474,10 @@ fn check_parts(request: &Value, result: &Value, seal: &Value) -> Check { c.push(r); } c.provider = said; + for r in super::planner::check(request, &bare) { + c.push(r); + } + c.planner = super::planner::statement(&bare); c } diff --git a/wai/wai-quantum/src/engine/mod.rs b/wai/wai-quantum/src/engine/mod.rs index 0338ed620..062dda2f0 100644 --- a/wai/wai-quantum/src/engine/mod.rs +++ b/wai/wai-quantum/src/engine/mod.rs @@ -17,6 +17,13 @@ //! form. //! - [`job`] (with `quantum_receipt`): a job end to end, planned, run and //! sealed, in the service's form; its check; and a program's lint. +//! - [`planner`] (with `quantum_receipt`): the planner under a contract. A job +//! says how exact its answer must be, what it may cost, by when, on how much +//! energy, and whether a provider may give it; every route the host can see +//! is priced with what is really known, those that cannot meet the contract +//! are rejected, the cheapest of the rest is chosen, and the reasoning is +//! sealed in the result. Nothing falls back in silence. A provider's answer +//! is shadowed by a classical method wherever one can reach it. //! - [`provider`] (with `quantum_receipt`): a job on the person's own //! provider (a processor, an on-premises device or a simulator, reached by //! a host that holds their credentials): what it may ask, its measured @@ -228,6 +235,8 @@ pub mod novelty; pub mod provider; #[cfg(feature = "quantum_receipt")] pub mod receipt; +#[cfg(feature = "quantum_receipt")] +pub mod planner; pub mod pulse; pub mod refusal; pub mod registry; diff --git a/wai/wai-quantum/src/engine/planner.rs b/wai/wai-quantum/src/engine/planner.rs new file mode 100644 index 000000000..b74ebe2d4 --- /dev/null +++ b/wai/wai-quantum/src/engine/planner.rs @@ -0,0 +1,1969 @@ +//! The planner under a contract: a job says what it wants of an answer (how +//! exact, what it may cost, by when, on how much energy, and whether a +//! provider may give it), and the planner lists every route it can see, prices +//! each with what is really known, rejects those that cannot meet the +//! contract, and chooses the cheapest that can. Its reasoning goes in the +//! result, where the receipt seals it. +//! +//! A job with no `contract` never comes here, and gives the bytes it gave. +//! +//! ```json fragment +//! "contract": { +//! "exactness": "exact", +//! "max_cost": { "amount": "0.50", "currency": "USD" }, +//! "deadline_seconds": 30, +//! "max_joules": 500, +//! "providers": "allowed" +//! } +//! ``` +//! +//! # No silent fallback +//! +//! A route is rejected unless it meets every member of the contract, and an +//! unknown is never read as a value that passes: a time nobody can state does +//! not meet a deadline, a price nobody states does not meet a ceiling, and a +//! run no live reading can stop does not meet an energy ceiling. So nothing falls +//! back from exact to approximate, from a simulator to a device, or the +//! reverse. If no route is left, the job is refused ([`refusal::NOTHING_MEETS`]) +//! with each route's reason. +//! +//! A contract that names no class keeps the class `auto` would give: `auto`'s +//! pick stands while it meets the rest of the contract, and when it does not, +//! only a route at least as exact may take its place. A device's counts are in +//! no classical class, so a device is reached only by asking for `measured` +//! (or `any`), or by naming the provider. +//! +//! # What is priced +//! +//! - A local method: free of money, its memory and work as the planner counts +//! them, its time at the planner's nominal rate ([`catalog::nominal_rate`]), +//! where its work predicts its time, and its energy as the host estimates it, +//! with what reads the run while it runs ([`Host::with_joules`]): a ceiling is +//! enforced by that reading, and an estimate promises nothing. +//! - A provider: the provider's own estimate, and what that leaves out, named +//! in `leaves_out`. A host gathers it ([`Quote`]): the engine never reaches +//! a provider itself. +//! +//! # What is stable across hosts +//! +//! `stable.digest` covers what the local routes that depend on nothing of the +//! host cost: the same for the same request and job memory, on every host of +//! one engine. `stable.choice` says whether the choice itself is. A provider +//! route, a method on a GPU and a registered method are the host's, and marked +//! `host_dependent`. +//! +//! # The shadow +//! +//! When a provider answers a contract job, a classical method that can reach +//! the same counts within the contract runs too, and the result carries both +//! with their distance ([`shadow`]). When none can, the result says so and why. +//! +//! The rules a verifier holds all this to are in +//! `wai/extensions/quantum-providers.md` section 8.7; [`check`] is the +//! reference's, and [`recheck`] runs what can be run again. + +use super::catalog::{self, Plan, Request}; +use super::energy::Held as Figure; +use super::fabric; +use super::receipt; +use super::refusal::{self, tag}; +use super::registry::{Identity, Job, Kind, Method, Question, Registry, declared}; +use serde_json::{Map, Value, json}; +use std::cmp::Ordering; + +/// The reasoning's format. +pub const FORMAT: &str = "wai.quantum.planner/1"; + +/// Every class a contract may want. `any` takes every route, and says so. +pub const CLASSES: [&str; 9] = ["bit-exact", "exact", "single", "bounded", "estimate", "heuristic", "measured", "simulated", "any"]; + +/// How long a shadow may be expected to take when the contract states no +/// deadline: a shadow is a check nobody asked to wait for, so it stays small. +pub const SHADOW_MAX_SECONDS: f64 = 300.0; + +/// A shadow's seed is the job's plus this, modulo 2^53: its own stream, so that +/// a seeded simulator's counts are not its counts by construction. +pub const SHADOW_SEED_OFFSET: u64 = 1 << 32; + +/// The most seconds a price may state (section 8.7): about 31,700 years. A +/// provider's estimate past it is not taken as a time. +pub const MAX_SECONDS: f64 = 1e12; + +/// The most characters an amount may have (section 8.7). A provider's estimate +/// past it is not taken as an amount, and a ceiling past it does not read. +pub const MAX_AMOUNT: usize = 64; + +/// The questions a job asks, by which `auto` orders the methods. +pub const QUESTIONS: [&str; 4] = ["noise", "counts", "expectations", "amplitudes"]; + +/// The reasons a verifier gives (section 8.7). +/// +/// The request's `contract` is not of its form. +pub const CONTRACT_FORM: &str = "contract_form"; +/// A contract job's `planner` is missing or not of its form, or a job with no +/// contract carries one. +pub const PLANNER_FORM: &str = "planner_form"; +/// A route's outcome is not what the contract and its price give. +pub const PLANNER_ROUTE: &str = "planner_route"; +/// The choice is not the route the rule picks, or not the route that ran. +pub const PLANNER_CHOICE: &str = "planner_choice"; +/// `stable` is not what the routes give. +pub const PLANNER_STABLE: &str = "planner_stable"; +/// `kept` is not what the contract and the result give. +pub const PLANNER_KEPT: &str = "planner_kept"; +/// The result's class does not meet the class wanted. +pub const CONTRACT_CLASS: &str = "contract_class"; +/// A provider's contract job's shadow is missing or not what its counts give. +pub const SHADOW: &str = "shadow"; +/// A request names a provider under a contract that does not allow one. +pub const CONTRACT_PROVIDER: &str = "contract_provider"; +/// A result's `stopped` is not of its form, or is on a job with no ceiling. +pub const STOPPED: &str = "stopped"; +/// The class of a run that gave no answer. +pub const STOPPED_CLASS: &str = "none"; + +/// Whether a result of class `got` meets a contract that wants `wanted`: the +/// table in section 8.7, not a ladder. A class with a stated error does not +/// meet one that asks for a rigorous bound, and a device's counts are in no +/// classical class. +pub fn meets(wanted: &str, got: &str) -> bool { + match wanted { + "any" => true, + "bit-exact" => got == "bit-exact", + "exact" => matches!(got, "bit-exact" | "exact"), + "single" => matches!(got, "bit-exact" | "exact" | "single"), + "bounded" => matches!(got, "bit-exact" | "exact" | "bounded"), + "estimate" => matches!(got, "bit-exact" | "exact" | "bounded" | "estimate"), + "heuristic" => matches!(got, "bit-exact" | "exact" | "single" | "bounded" | "estimate" | "heuristic"), + "measured" => got == "measured", + "simulated" => got == "simulated", + _ => false, + } +} + +/// The classes of the table from the most exact: a route's class is the first of +/// them that every class its method declares meets. +const LADDER: [&str; 6] = ["bit-exact", "exact", "single", "bounded", "estimate", "heuristic"]; + +/// How exact a class is, for a shadow's choice among classical methods: the +/// strongest first. +fn strength(class: &str) -> u32 { + match class { + "bit-exact" => 0, + "exact" => 1, + "single" => 2, + "bounded" => 3, + "estimate" => 4, + "heuristic" => 5, + _ => 6, + } +} + +/// A request's contract, read and checked. +#[derive(Clone, Debug, Default, PartialEq)] +#[non_exhaustive] +pub struct Contract { + /// The class wanted; one of [`CLASSES`]. + pub exactness: Option, + /// The most it may cost, its amount in decimals and its currency. + pub max_cost: Option<(String, String)>, + /// When it must be done by, in seconds from when it starts. + pub deadline_seconds: Option, + /// The most energy it may take, in joules. + pub max_joules: Option, + /// Whether a provider may be used: `Some(true)` for `allowed`, + /// `Some(false)` for `never`, and `None` when the contract does not say, + /// which is `never`. + pub providers: Option, +} + +/// Whether a request holds a contract: a `contract` member other than `null`. +pub fn has_contract(v: &Value) -> bool { + v.get("contract").is_some_and(|c| !c.is_null()) +} + +/// Whether `s` is an amount in decimals: digits, and optionally `.` and digits, +/// at most [`MAX_AMOUNT`] characters in all. +pub fn is_decimal(s: &str) -> bool { + if s.len() > MAX_AMOUNT { + return false; + } + let (whole, frac) = s.split_once('.').map_or((s, None), |(a, b)| (a, Some(b))); + !whole.is_empty() && whole.bytes().all(|b| b.is_ascii_digit()) && frac.is_none_or(|f| !f.is_empty() && f.bytes().all(|b| b.is_ascii_digit())) +} + +/// Two amounts in decimals compared exactly, with no double between them. +pub fn decimal_cmp(a: &str, b: &str) -> Ordering { + let parts = |s: &'_ str| -> (String, String) { + let (whole, frac) = s.split_once('.').unwrap_or((s, "")); + let w = whole.trim_start_matches('0').to_string(); + (w, frac.trim_end_matches('0').to_string()) + }; + let ((wa, fa), (wb, fb)) = (parts(a), parts(b)); + wa.len().cmp(&wb.len()).then_with(|| wa.cmp(&wb)).then_with(|| fa.cmp(&fb)) +} + +impl Contract { + /// The contract of the job `v`, or `None` when it has none. Anything else + /// that does not read is refused ([`refusal::CONTRACT_FORM`]): a member read + /// as absent would be a requirement dropped in silence. + pub fn read(v: &Value) -> Result, String> { + let Some(c) = v.get("contract").filter(|c| !c.is_null()) else { return Ok(None) }; + let bad = |m: String| tag(refusal::CONTRACT_FORM, m); + let Some(o) = c.as_object() else { return Err(bad("\"contract\" is an object: exactness, max_cost, deadline_seconds, max_joules and providers, each optional".into())) }; + if let Some(k) = o.keys().find(|k| !["exactness", "max_cost", "deadline_seconds", "max_joules", "providers"].contains(&k.as_str())) { + return Err(bad(format!("contract: {k:?} is no member of a contract: it takes exactness, max_cost, deadline_seconds, max_joules and providers"))); + } + let member = |k: &str| o.get(k).filter(|x| !x.is_null()); + let exactness = match member("exactness") { + None => None, + Some(e) => match e.as_str().filter(|s| CLASSES.contains(s)) { + Some(s) => Some(s.to_string()), + None => return Err(bad(format!("contract: exactness is one of {}, not {e}", CLASSES.join(", ")))), + }, + }; + let max_cost = match member("max_cost") { + None => None, + Some(m) => { + let (a, cur) = (m.get("amount").and_then(Value::as_str), m.get("currency").and_then(Value::as_str)); + match (a.filter(|a| is_decimal(a)), cur.filter(|c| !c.is_empty()), m.as_object().map(Map::len)) { + (Some(a), Some(cur), Some(2)) => Some((a.to_string(), cur.to_string())), + _ => return Err(bad(format!("contract: max_cost is {{\"amount\": \"0.50\", \"currency\": \"USD\"}}, the amount in decimals as a string, not {m}"))), + } + } + }; + let positive = |k: &str| -> Result, String> { + match member(k) { + None => Ok(None), + Some(x) => match x.as_f64().filter(|x| x.is_finite() && *x > 0.0) { + Some(x) => Ok(Some(x)), + None => Err(bad(format!("contract: {k} is a number above zero, not {x}"))), + }, + } + }; + let deadline_seconds = positive("deadline_seconds")?; + let max_joules = positive("max_joules")?; + let providers = match member("providers") { + None => None, + Some(x) => match x.as_str() { + Some("never") => Some(false), + Some("allowed") => Some(true), + _ => return Err(bad(format!("contract: providers is never or allowed, not {x}"))), + }, + }; + Ok(Some(Contract { exactness, max_cost, deadline_seconds, max_joules, providers })) + } +} + +/// What a host brings of one of the person's providers: what it would run, what +/// its provider's estimate says, and what the estimate leaves out. Asking for +/// it spends nothing. The engine never reaches a provider itself. +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct Quote { + /// The person's name for the provider. + pub name: String, + /// The device, as the result would name it. + pub device: String, + /// `silicon`, or `simulator` or `emulator`, alone or with what it is. + pub provenance: String, + /// The provider states this simulator's results are approximate. + pub approximate: bool, + /// Why this provider cannot run this job, when it cannot: the rest is then + /// not known. + pub cannot: Option, + /// What it costs: `{"free": true}`, `{"free": false, "amount", "currency"}` + /// with an optional `unit`, and `"at_least": true` when the amount is the + /// least it can come to, or `{"free": false, "unknown": "why"}`. + pub money: Value, + /// How long the provider says it takes, queue included. + pub seconds: Option, + /// What the estimate leaves out: words of [`LEFT_OUT`]. + pub leaves_out: Vec, + /// What the job would ask of the device: its shots and the program's + /// gates, and its expected success when a calibration states one. + pub program: Value, +} + +/// What an estimate can leave out (section 8.7). +pub const LEFT_OUT: [&str; 7] = ["time", "amount", "energy", "mitigation", "decoder", "charged", "cancel"]; + +impl Quote { + /// A provider that can run the job, with nothing known of it yet: its + /// cost unknown and its time not stated, each left out until a host says. + pub fn new(name: impl Into, device: impl Into, provenance: impl Into) -> Quote { + Quote { + name: name.into(), + device: device.into(), + provenance: provenance.into(), + approximate: false, + cannot: None, + money: json!({ "free": false, "unknown": "the provider states no cost" }), + seconds: None, + leaves_out: Vec::new(), + program: json!({}), + } + } + + /// A provider that cannot run the job, and why. + pub fn cannot(name: impl Into, why: impl Into) -> Quote { + let mut q = Quote::new(name, "", ""); + q.cannot = Some(why.into()); + q + } + + fn class(&self) -> &'static str { + match super::provider::class_of_provenance(&self.provenance) { + Some("measured") => "measured", + Some(_) => "simulated", + None => "unknown", + } + } +} + +/// What a host says of a plan's energy: its estimate, and what reads the run while +/// it runs ([`Figure`]). +pub type Joules<'a> = dyn Fn(&Plan) -> Figure + 'a; + +/// What a host brings to the planner. +#[non_exhaustive] +pub struct Host<'a> { + /// The memory one job may take here, bytes. + pub job_bytes: u64, + /// What each of the person's providers says of this job. + pub quotes: Vec, + /// The host's energy estimate, where it has one. + pub joules: Option<&'a Joules<'a>>, +} + +impl<'a> Host<'a> { + /// A host that reaches no provider and estimates no energy. + pub fn new(job_bytes: u64) -> Host<'a> { + Host { job_bytes, quotes: Vec::new(), joules: None } + } + + pub fn with_quotes(mut self, quotes: Vec) -> Host<'a> { + self.quotes = quotes; + self + } + + pub fn with_joules(mut self, joules: &'a Joules<'a>) -> Host<'a> { + self.joules = Some(joules); + self + } +} + +/// What the planner chose. +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub enum Choice { + /// One of the engine's methods, with its plan. + Local(Plan), + /// One of the person's providers, by name. + Provider(String), +} + +/// A contract met: the route chosen and the reasoning a result carries. +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct Decision { + pub choice: Choice, + pub reasoning: Value, +} + +/// A contract considered: the reasoning, with `choice` `null` and `refusal` +/// set when no route meets it. Nothing is refused here that a plan's surface +/// would want to show: each route's price or reason is in it. +#[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] +pub struct Considered { + pub reasoning: Value, + pub plan: Option, + /// The refusal, ending with its code, when no route meets the contract. + pub refusal: Option, +} + +/// A whole number as JSON, or the double nearest it past what every reader reads +/// alike: a price is sealed, and an inexact whole number invalidates a receipt. +fn whole(x: u64) -> Value { + if x < (1 << 53) { json!(x) } else { json!(x as f64) } +} + +pub fn is_gpu(method: &str) -> bool { + matches!(method, "statevector_single" | "cutrank_single") +} + +/// The class a method's result has at worst, as far as the plan can say: the +/// weakest it declares, or for the methods whose class the job fixes, that one. +fn class_of(m: &dyn Method, r: Option<&Request>, plan: Option<&Plan>, target: bool) -> String { + let worst = || worst_of(&m.classes()); + match (m.name(), r) { + ("stabilizer", Some(r)) => if r.noise.is_some() || target { "estimate".into() } else { "exact".into() }, + ("stabilizer_rank", Some(r)) => if ["terms", "epsilon"].iter().any(|k| r.options.get(*k).is_some_and(|x| !x.is_null())) { "estimate".into() } else { "exact".into() }, + // The table's precision is chosen by the memory the job has, and the plan says which. + ("cutrank", _) => match plan { + Some(p) if p.why.contains("single precision") => "single".into(), + _ => "exact".into(), + }, + _ => worst(), + } +} + +/// The weakest of the classes a method declares: the first of the ladder that +/// each of them meets. +fn worst_of>(declared: &[S]) -> String { + match declared { + [] => "unknown".to_string(), + [one] => one.as_ref().to_string(), + many => LADDER.iter().find(|c| many.iter().all(|d| meets(c, d.as_ref()))).map_or_else(|| "unknown".to_string(), |c| c.to_string()), + } +} + +/// A local route's time: at the planner's nominal rate, where its work predicts +/// its time. +fn time_of(p: &Plan) -> Value { + match catalog::nominal_rate(&p.method) { + Some(rate) => json!({ "seconds": p.work as f64 / rate, "basis": "nominal" }), + None => json!({ "seconds": null, "why": format!("the work the planner counts for {} does not predict its time", p.method) }), + } +} + +/// A local route's energy: the host's estimate, or why there is none. +fn energy_of(p: &Plan, host: &Host<'_>) -> Value { + let Some(f) = host.joules else { + return json!({ "joules": null, "why": "this host estimates no job's energy before it runs", "unwatched": "this host reads no run while it runs" }); + }; + let held = f(p); + let mut e = match held.estimate { + Ok((joules, basis)) => json!({ "joules": joules, "basis": basis }), + Err(why) => json!({ "joules": null, "why": why }), + }; + match held.watch { + Ok(what) => e["watch"] = json!(what), + Err(why) => e["unwatched"] = json!(why), + } + e +} + +fn local_route(m: &dyn Method, identity: Option<&Identity>, r: Option<&Request>, plan: Option<&Plan>, host: &Host<'_>, target: bool, rank: Option) -> Value { + let mut route = json!({ + "route": format!("method:{}", m.name()), + "kind": "local", + "method": m.name(), + "class": class_of(m, r, plan, target), + "host_dependent": is_gpu(m.name()) || identity.is_some_and(|i| !i.is_builtin()), + "auto_rank": rank, + "price": null, + }); + if let Some(p) = plan { + route["price"] = json!({ + "money": { "free": true }, + "time": time_of(p), + "memory_bytes": whole(p.memory_bytes), + "work": whole(p.work), + "energy": energy_of(p, host), + "leaves_out": [], + }); + } + route +} + +fn provider_route(q: &Quote) -> Value { + let mut route = json!({ + "route": format!("provider:{}", q.name), + "kind": "provider", + "provider": q.name, + "class": q.class(), + "host_dependent": true, + "price": null, + }); + if q.cannot.is_some() { + route["class"] = json!("unknown"); + return route; + } + route["device"] = json!(q.device); + route["provenance"] = json!(q.provenance); + if q.approximate { + route["approximate"] = json!(true); + } + // What a price may state is bounded (section 8.7): past it, a provider's + // estimate is not taken as a time or an amount, and is an unknown. + let time = match q.seconds { + Some(s) if (0.0..=MAX_SECONDS).contains(&s) => json!({ "seconds": s, "basis": "provider" }), + Some(s) => json!({ "seconds": null, "why": format!("the provider's estimate states {s} s, past the {MAX_SECONDS} s a price may state") }), + None => json!({ "seconds": null, "why": "the provider's estimate states no time" }), + }; + let mut money = q.money.clone(); + if let Some(n) = money["amount"].as_str().map(|a| a.chars().count()).filter(|n| *n > MAX_AMOUNT) { + money = json!({ "free": false, "unknown": format!("the provider's estimate states an amount of {n} characters, past the {MAX_AMOUNT} an amount may have") }); + } + route["price"] = json!({ + "money": money, + "time": time, + "memory_bytes": null, + "work": null, + "energy": { "joules": null, "why": "no provider states a job's energy before it runs" }, + "leaves_out": q.leaves_out, + "program": q.program, + }); + route +} + +/// What a route is held to. +struct Held<'a> { + contract: &'a Contract, + /// The route the job names: the provider or the method its request names, + /// or the one method a device target's job runs on. + named: Option<&'a str>, + fabric: Fab, + wanted: Option<&'a str>, + /// Whether `wanted` is the class the contract names, rather than the one the + /// job keeps: only a class the contract names refuses an approximate + /// simulator a job named. + from_contract: bool, + job_bytes: f64, +} + +#[derive(Clone, Copy, PartialEq)] +enum Fab { + Free, + Cpu, + Placed, +} + +fn fab_of(v: &Value) -> Fab { + match v.get("fabric") { + None | Some(Value::Null) => Fab::Free, + Some(Value::String(s)) if s == "auto" => Fab::Free, + Some(Value::String(s)) if s == "cpu" => Fab::Cpu, + _ => Fab::Placed, + } +} + +/// What a request itself names: `provider:` for the provider it names, +/// else `method:` for a method other than `auto`. +fn request_names(v: &Value) -> Option { + if let Some(p) = v.get("provider").and_then(Value::as_str) { + return Some(format!("provider:{p}")); + } + v.get("method").and_then(Value::as_str).filter(|m| *m != "auto").map(|m| format!("method:{m}")) +} + +/// Whether a request names a device target. +fn names_target(v: &Value) -> bool { + v.get("target").is_some_and(|t| !t.is_null()) +} + +/// The question a job asks, which orders the methods `auto` tries (section +/// 8.7): `noise` for a job with a noise model; else `counts` when it asks for +/// shots (1024 when it gives none and asks for no observable and no amplitude); +/// else `expectations` when it asks for observables and no amplitude; else +/// `amplitudes`. Read from the request alone, as any verifier reads it. +pub fn question_of(v: &Value) -> &'static str { + let listed = |k: &str| v.get(k).and_then(Value::as_array).is_some_and(|a| !a.is_empty()); + let (observables, amplitudes) = (listed("observables"), listed("amplitudes")); + let shots = v.get("shots").and_then(Value::as_u64).unwrap_or(if !observables && !amplitudes { 1024 } else { 0 }); + if v.get("noise").is_some_and(|n| !n.is_null()) { + "noise" + } else if shots > 0 { + "counts" + } else if observables && !amplitudes { + "expectations" + } else { + "amplitudes" + } +} + +fn question(q: &str) -> Question { + match q { + "noise" => Question::Noise, + "counts" => Question::Counts, + "expectations" => Question::Expectations, + _ => Question::Amplitudes, + } +} + +/// The route `auto` picks, from what the routes state (section 8.7): none for a +/// job that names a route; `method:statevector` for one placed on the fabric's +/// members, where it is priced; otherwise the priced local route of the least +/// `auto_rank`, the first listed of equal ranks. Every verifier recomputes it. +fn auto_of(routes: &[Value], request: &Value, named: Option<&str>) -> Option { + if named.is_some() { + return None; + } + if fab_of(request) == Fab::Placed { + return routes.iter().find(|r| r["route"] == "method:statevector" && r["kind"] == "local" && r["price"].is_object()).map(|_| "method:statevector".to_string()); + } + let by_value = |x: f64, y: f64| x.partial_cmp(&y).unwrap_or(Ordering::Equal); + routes + .iter() + .enumerate() + .filter(|(_, r)| r["kind"] == "local" && r["price"].is_object()) + .filter_map(|(i, r)| r["auto_rank"].as_f64().map(|k| (k, i, r))) + .min_by(|a, b| by_value(a.0, b.0).then(a.1.cmp(&b.1))) + .and_then(|(_, _, r)| r["route"].as_str().map(str::to_string)) +} + +/// The first rule of section 8.7 a route breaks, in its order, or `None` when +/// it meets the contract. Its class is judged before anything about its price, +/// so that the code says the same whatever a host can run. An unknown never +/// passes where something is asked of it. +fn gate(route: &Value, h: &Held<'_>) -> Option<&'static str> { + let name = route["route"].as_str().unwrap_or(""); + let (method, provider) = (name.strip_prefix("method:"), name.strip_prefix("provider:")); + if let Some(n) = h.named + && name != n + { + return Some("not_named"); + } + if h.named.is_none() { + match h.fabric { + Fab::Placed if method != Some("statevector") => return Some("fabric"), + Fab::Cpu if method.is_some_and(is_gpu) => return Some("fabric"), + _ => {} + } + } + let class = route["class"].as_str().unwrap_or(""); + // A provider that cannot run the job has no class to judge. + if class == "unknown" && route["price"].is_null() { + return Some("cannot"); + } + match h.wanted { + Some(w) if !meets(w, class) || (h.from_contract && w == "simulated" && route["approximate"] == true) => return Some("class"), + None if provider.is_some() => return Some("class"), + _ => {} + } + let price = &route["price"]; + if !price.is_object() { + return Some("cannot"); + } + if price["memory_bytes"].as_f64().is_some_and(|m| m > h.job_bytes) { + return Some("memory"); + } + if provider.is_some() && h.contract.providers != Some(true) { + return Some("providers"); + } + if let Some(d) = h.contract.deadline_seconds { + match price["time"]["seconds"].as_f64() { + None => return Some("deadline_unknown"), + Some(s) if s > d => return Some("deadline"), + _ => {} + } + } + if provider.is_some() && price["money"]["free"] != true { + let (amount, currency) = (price["money"]["amount"].as_str().filter(|a| is_decimal(a)), price["money"]["currency"].as_str()); + match &h.contract.max_cost { + // A provider named by the job is the person's choice, as it is with + // no contract: its cost is shown, and it runs on their confirmation. + None if provider.is_some_and(|_| h.named == Some(name)) => {} + None => return Some("cost_no_ceiling"), + Some((most, cur)) => match (amount, currency) { + (Some(a), Some(c)) if c == cur => { + if decimal_cmp(a, most) == Ordering::Greater { + return Some("cost"); + } + // The least it can come to: what it will come to is not known. + if price["money"]["at_least"] == true { + return Some("cost_at_least"); + } + } + (Some(_), Some(_)) => return Some("cost_currency"), + _ => return Some("cost_unknown"), + }, + } + } + if let Some(j) = h.contract.max_joules { + match price["energy"]["joules"].as_f64() { + _ if !price["energy"]["watch"].is_string() => return Some("energy_unwatched"), + Some(x) if x > j => return Some("energy"), + _ => {} + } + } + None +} + +/// Why a route was rejected, in a sentence, for a code [`gate`] gave. +fn gate_why(code: &str, route: &Value, h: &Held<'_>) -> String { + let price = &route["price"]; + let class = route["class"].as_str().unwrap_or("unknown"); + let ceiling = || h.contract.max_cost.as_ref().map_or(String::new(), |c| format!("{} {}", c.0, c.1)); + match code { + "not_named" => "the job names another route".to_string(), + "fabric" => "the job's placement on the fabric is not this route's".to_string(), + "class" => match h.wanted { + Some(w) if class == "heuristic" && matches!(w, "bit-exact" | "exact" | "single" | "bounded" | "estimate") => format!("its class is heuristic, and exact only when nothing is truncated, which it cannot know before it runs; the job wants {w}"), + Some(w) if w == "simulated" && route["approximate"] == true => "its provider states this simulator is approximate, and the contract wants a simulator's counts that are not".to_string(), + Some(w) => format!("its class is {class}, and the job wants {w}"), + None => format!("its class is {class}; the job names no class, and nothing the planner would do today gives this one: ask for measured or any, or name the provider"), + }, + "memory" => format!("it takes {} bytes, and a job here takes at most {}", price["memory_bytes"], h.job_bytes), + "providers" => "the contract does not allow a provider: under a contract one is used only with providers: allowed".to_string(), + "deadline_unknown" => format!("its time is not known, so it cannot be held to the deadline of {} s: {}", h.contract.deadline_seconds.unwrap_or(0.0), price["time"]["why"].as_str().unwrap_or("")), + "deadline" => format!("about {} s, past the deadline of {} s", price["time"]["seconds"], h.contract.deadline_seconds.unwrap_or(0.0)), + "cost_no_ceiling" => format!("{}: it costs money or its cost is unknown, and the contract gives no ceiling to hold it to; give max_cost, or name the provider", money_said(&price["money"])), + "cost_unknown" => format!("{}: an unknown cost does not meet a ceiling", money_said(&price["money"])), + "cost_currency" => format!("{}, and the ceiling is in {}: the planner converts no currency", money_said(&price["money"]), h.contract.max_cost.as_ref().map_or("", |c| c.1.as_str())), + "cost" => format!("{}, above the ceiling of {}", money_said(&price["money"]), ceiling()), + "cost_at_least" => format!("{}: the least it can come to, and what the job takes decides the rest, so it is not known to be within the ceiling of {}", money_said(&price["money"]), ceiling()), + "energy_unwatched" => format!("no reading of it can stop it at the ceiling of {} J, and only a live reading holds a ceiling: {}", h.contract.max_joules.unwrap_or(0.0), price["energy"]["unwatched"].as_str().unwrap_or("nothing here reads this route while it runs")), + "energy" => format!("an estimate of {} J is past the ceiling of {} J: {}", price["energy"]["joules"], h.contract.max_joules.unwrap_or(0.0), price["energy"]["basis"].as_str().unwrap_or("")), + other => other.to_string(), + } +} + +fn money_said(m: &Value) -> String { + match (m["free"].as_bool(), m["amount"].as_str(), m["currency"].as_str(), m["unknown"].as_str()) { + (Some(true), ..) => "free".to_string(), + (_, Some(a), Some(c), _) if m["at_least"] == true => format!("at least {a} {c}"), + (_, Some(a), Some(c), _) => format!("{a} {c}"), + (_, _, _, Some(u)) => u.to_string(), + _ => "its cost is unknown".to_string(), + } +} + +/// A route's money in the order: free first, then an amount in decimals by its +/// value, then any other. +fn money_rank(r: &Value) -> (u8, Option<&str>) { + let m = &r["price"]["money"]; + if m["free"] == true { + (0, None) + } else if let Some(a) = m["amount"].as_str().filter(|a| is_decimal(a)) { + (1, Some(a)) + } else { + (2, None) + } +} + +/// A time in the order: its seconds to the nearest whole millisecond, halves up. +fn millis(r: &Value) -> Option { + r["price"]["time"]["seconds"].as_f64().map(|s| (s * 1000.0 + 0.5).floor()) +} + +/// Which of two routes that meet the contract is cheaper: less money (free +/// first, then the lesser amount in decimals, then any other), then less time to +/// the nearest millisecond (a stated time before an unknown one), a local route +/// before a provider's, less memory, and then by name, so that the order is +/// total and every verifier finds the same route. +fn cheaper(a: &Value, b: &Value) -> Ordering { + let ((ra, aa), (rb, ab)) = (money_rank(a), money_rank(b)); + let money_order = ra.cmp(&rb).then_with(|| match (aa, ab) { + (Some(x), Some(y)) => decimal_cmp(x, y), + _ => Ordering::Equal, + }); + // By value: -0.0 is 0 (a JSON number has no NaN). + let by_value = |x: f64, y: f64| x.partial_cmp(&y).unwrap_or(Ordering::Equal); + let time_order = match (millis(a), millis(b)) { + (Some(x), Some(y)) => by_value(x, y), + (Some(_), None) => Ordering::Less, + (None, Some(_)) => Ordering::Greater, + (None, None) => Ordering::Equal, + }; + let local = |r: &Value| r["kind"] != "local"; + let memory = |r: &Value| r["price"]["memory_bytes"].as_f64().unwrap_or(0.0); + money_order + .then(time_order) + .then_with(|| local(a).cmp(&local(b))) + .then_with(|| by_value(memory(a), memory(b))) + .then_with(|| a["route"].as_str().unwrap_or("").as_bytes().cmp(b["route"].as_str().unwrap_or("").as_bytes())) +} + +/// The route the rule picks from `routes`, of those `h` lets through: `auto`'s +/// pick when the contract names no class and it meets the rest, else the +/// cheapest. Judged here, whatever a route's outcome says of itself. +fn pick<'a>(routes: &'a [Value], auto: Option<&str>, h: &Held<'_>) -> Option<&'a Value> { + let met = |r: &&Value| gate(r, h).is_none(); + if h.contract.exactness.is_none() + && let Some(a) = auto + && let Some(r) = routes.iter().filter(met).find(|r| r["route"] == a) + { + return Some(r); + } + routes.iter().filter(met).min_by(|a, b| cheaper(a, b)) +} + +/// `stable`: what the routes that depend on nothing of the host cost, in a +/// digest any verifier recomputes, and whether the choice depends on the host. +fn stable_of(routes: &[Value], job_bytes: &Value, choice: Option<&str>, contract: &Contract) -> Value { + let covered: Vec<&Value> = routes.iter().filter(|r| r["kind"] == "local" && r["host_dependent"] == false).collect(); + let facts: Vec = covered.iter().map(|r| json!({ "route": r["route"], "class": r["class"], "seconds": r["price"]["time"]["seconds"], "memory_bytes": r["price"]["memory_bytes"], "work": r["price"]["work"] })).collect(); + let digest = blake3::hash(&receipt::canonical(&json!({ "job_bytes": job_bytes, "routes": facts }))).to_hex().to_string(); + let chosen_stable = choice.is_some_and(|c| covered.iter().any(|r| r["route"] == c)); + let others = routes.iter().filter(|r| r["host_dependent"] != false).all(|r| matches!(r["rejected"]["code"].as_str(), Some("not_named" | "fabric" | "class"))); + json!({ + "scope": "digest: what each route that depends on nothing of the host costs, the same for this request and job memory on every host of one engine; choice: whether the route chosen is one of those whatever the host", + "routes": covered.iter().map(|r| r["route"].clone()).collect::>(), + "digest": digest, + "choice": chosen_stable && others && contract.providers != Some(true) && contract.max_joules.is_none(), + }) +} + +/// The local routes of a job, each priced or with why it cannot. +struct Local { + routes: Vec, + /// Each route that can run, with its plan. + plans: Vec<(String, Plan)>, + /// Why each route that cannot run cannot. + cannot: Vec<(String, String)>, + /// The route the job names, where it names one. + named: Option, + read: Option, +} + +fn local_routes(reg: &Registry, v: &Value, host: &Host<'_>, q: Question) -> Result { + let identity = |m: &dyn Method| reg.identity(Kind::Method, m.name()); + let job_bytes = host.job_bytes; + // A program its method reads itself, and a job on a device target, have one + // route: the method that reads it, and the method the device's noise takes. + let target = crate::engine::targets::job::names_target(v); + if catalog::reads_own(reg, v).is_some() || target { + let p = catalog::plan_plain(reg, v, job_bytes)?; + let m = reg.method(&p.method).ok_or_else(|| format!("internal: no method {}", p.method))?; + let route = local_route(m, identity(m), None, Some(&p), host, target, m.auto_rank(q)); + let name = route["route"].as_str().unwrap_or("").to_string(); + return Ok(Local { routes: vec![route], plans: vec![(name.clone(), p)], cannot: Vec::new(), named: Some(name), read: None }); + } + let (r, uses) = catalog::read_in(reg, v)?; + let named_method = (r.method != "auto").then(|| r.method.clone()); + if let Some(n) = &named_method + && reg.method(n).is_none() + { + return Err(tag(refusal::UNKNOWN_METHOD, format!("unknown method {n}; GET /v1/methods lists them"))); + } + let need = catalog::intent_need(reg, v, &r, job_bytes)?; + let mut out = Local { routes: Vec::new(), plans: Vec::new(), cannot: Vec::new(), named: named_method.as_ref().map(|n| format!("method:{n}")), read: None }; + { + let job = Job::new(reg, v, job_bytes, Some(&r), &uses); + for m in reg.methods() { + let name = format!("method:{}", m.name()); + let unasked = named_method.as_ref().is_some_and(|n| n != m.name()); + let planned = if unasked { + None + } else if m.reads_program() { + out.cannot.push((name.clone(), format!("{} reads its own program, and runs only when a job names it", m.name()))); + None + } else { + match catalog::plan_one(m, &job) { + Ok(mut p) => { + p.memory_bytes = p.memory_bytes.max(need); + Some(p) + } + Err(e) => { + out.cannot.push((name.clone(), e)); + None + } + } + }; + out.routes.push(local_route(m, identity(m), Some(&r), planned.as_ref(), host, false, m.auto_rank(q))); + if let Some(p) = planned { + out.plans.push((name, p)); + } + } + } + out.read = Some(r); + Ok(out) +} + +/// Whether a job that names a provider may reach it: under a contract a provider +/// is used only where the contract allows one, the job's own named one among +/// them, and `providers: never` is the default. A host holds this before it asks +/// the provider anything. +pub fn provider_allowed(v: &Value) -> Result<(), String> { + let Some(contract) = Contract::read(v)? else { return Ok(()) }; + // A class no provider's counts have: none is asked anything for it. + if v.get("provider").is_some_and(|p| !p.is_null()) && contract.providers == Some(true) && contract.exactness.as_deref().is_some_and(|w| !matches!(w, "measured" | "simulated" | "any")) { + return Err(tag(refusal::NOTHING_MEETS, format!("the job names a provider, and its contract wants {}: no provider's counts are of that class, so none is asked", contract.exactness.as_deref().unwrap_or("")))); + } + if v.get("provider").is_some_and(|p| !p.is_null()) && contract.providers != Some(true) { + return Err(tag(refusal::CONTRACT_FORM, "the job names a provider, and its contract does not allow one: under a contract a provider is used only with providers: allowed")); + } + Ok(()) +} + +/// `contract` weighed against every route `host` can see. An error is a job that +/// does not read, or a contract that does not; a contract no route meets gives +/// the reasoning with the refusal in it. +pub fn consider(reg: &Registry, v: &Value, host: &Host<'_>) -> Result { + let contract = Contract::read(v)?.ok_or_else(|| "internal: a job with no contract was brought to the planner".to_string())?; + provider_allowed(v)?; + let provider = v.get("provider").and_then(Value::as_str); + if v.get("provider").is_some_and(|p| !p.is_null()) && !provider.is_some_and(|p| host.quotes.iter().any(|q| q.name == p)) { + // Refused as a job that names a provider is refused where none is reached. + catalog::read_in(reg, v)?; + return Err(tag(refusal::PROVIDER_HERE, "this job names a provider this host has not brought")); + } + let q = question_of(v); + // A job that names a provider runs on it: the methods are listed unpriced, + // each with the class it has on this job, which its shadow's class must be. + let mut local = if let Some(p) = provider { + let mut l = Local { routes: Vec::new(), plans: Vec::new(), cannot: Vec::new(), named: Some(format!("provider:{p}")), read: None }; + let shadow = shadow_request(v); + let read = shadow.as_ref().and_then(|req| catalog::read_in(reg, req).ok()); + for m in reg.methods() { + let mut route = local_route(m, reg.identity(Kind::Method, m.name()), read.as_ref().map(|(r, _)| r), None, host, false, m.auto_rank(question(q))); + if let (Some(req), Some((r, uses))) = (&shadow, &read) + && !m.reads_program() + && let Ok(plan) = catalog::plan_one(m, &Job::new(reg, req, host.job_bytes, Some(r), uses)) + { + route["class"] = json!(class_of(m, Some(r), Some(&plan), false)); + } + l.routes.push(route); + } + l + } else { + local_routes(reg, v, host, question(q))? + }; + let named = local.named.take(); + let mut routes = std::mem::take(&mut local.routes); + routes.extend(host.quotes.iter().map(provider_route)); + let quote_cannot = |name: &str| host.quotes.iter().find(|q| format!("provider:{}", q.name) == name).and_then(|q| q.cannot.clone()); + let auto = auto_of(&routes, v, named.as_deref()); + // What the job wants: what the contract says, else what it would have had. + let class_of_route = |name: &str| routes.iter().find(|r| r["route"] == name).and_then(|r| r["class"].as_str()).map(str::to_string); + let (wanted, wanted_from) = match (&contract.exactness, &named, &auto) { + (Some(w), _, _) => (Some(w.clone()), Some("contract")), + (None, Some(n), _) => (class_of_route(n), Some("named")), + (None, None, Some(a)) => (class_of_route(a), Some("auto")), + (None, None, None) => (None, None), + }; + let job_bytes = whole(host.job_bytes); + let held = Held { contract: &contract, named: named.as_deref(), fabric: fab_of(v), wanted: wanted.as_deref(), from_contract: wanted_from == Some("contract"), job_bytes: host.job_bytes as f64 }; + for route in &mut routes { + let name = route["route"].as_str().unwrap_or("").to_string(); + match gate(route, &held) { + None => route["outcome"] = json!("met"), + Some(code) => { + let why = match code { + "cannot" => local.cannot.iter().find(|(n, _)| *n == name).map(|(_, w)| w.clone()).or_else(|| quote_cannot(&name)).unwrap_or_else(|| "it cannot take this job".to_string()), + _ => gate_why(code, route, &held), + }; + route["outcome"] = json!("rejected"); + route["rejected"] = json!({ "code": code, "why": why }); + } + } + } + let total = routes.len(); + let met = routes.iter().filter(|r| r["outcome"] != "rejected").count(); + let chosen = pick(&routes, auto.as_deref(), &held).map(|r| r["route"].as_str().unwrap_or("").to_string()); + if let Some(c) = &chosen + && let Some(r) = routes.iter_mut().find(|r| r["route"] == c.as_str()) + { + r["outcome"] = json!("chosen"); + } + let mut reasoning = json!({ + "format": FORMAT, + "wanted": wanted, + "wanted_from": wanted_from, + "named": named, + "question": q, + "auto": auto, + "host": { + "job_bytes": job_bytes, + "providers": host.quotes.iter().map(|q| q.name.clone()).collect::>(), + }, + "routes": routes, + "choice": chosen, + }); + let Some(chosen) = chosen else { + let reasons: Vec = reasoning["routes"].as_array().into_iter().flatten().filter(|r| !matches!(r["rejected"]["code"].as_str(), Some("not_named"))).map(|r| format!("{}: {}", r["route"].as_str().unwrap_or(""), r["rejected"]["why"].as_str().unwrap_or(""))).collect(); + let refusal = tag(refusal::NOTHING_MEETS, format!("no route meets this contract — {}", reasons.join("; "))); + reasoning["why"] = json!(refusal); + reasoning["refusal"] = refusal::refusal_json(&refusal); + reasoning["stable"] = stable_of(reasoning["routes"].as_array().map_or(&[], Vec::as_slice), &reasoning["host"]["job_bytes"], None, &contract); + return Ok(Considered { reasoning, plan: None, refusal: Some(refusal) }); + }; + let said = match wanted_from { + Some("named") => format!("the route the job names, which meets its contract ({met} of {total} routes)"), + Some("auto") if auto.as_deref() == Some(chosen.as_str()) => format!("what auto picks, which meets the contract: the contract names no class, so it keeps auto's ({met} of {total} routes meet it)"), + Some("auto") => format!("auto's pick does not meet the contract, so the cheapest route at least as exact ({met} of {total} routes meet it)"), + _ => format!("the cheapest of the {met} of {total} routes that meet the contract"), + }; + reasoning["why"] = json!(said); + reasoning["stable"] = stable_of(reasoning["routes"].as_array().map_or(&[], Vec::as_slice), &reasoning["host"]["job_bytes"], Some(&chosen), &contract); + let mut plan = local.plans.iter().find(|(n, _)| *n == chosen).map(|(_, p)| p.clone()); + if let Some(p) = &mut plan { + p.why = format!("{}; {said}", p.why); + if let Some(r) = &local.read { + fabric::admit(v, r, p)?; + } + } + if chosen.starts_with("provider:") { + reasoning["shadow"] = shadow_plan(reg, v, host, &contract, provider_seconds(&reasoning["routes"], &chosen)); + } + Ok(Considered { reasoning, plan, refusal: None }) +} + +fn provider_seconds(routes: &Value, chosen: &str) -> Option { + routes.as_array()?.iter().find(|r| r["route"] == chosen)?["price"]["time"]["seconds"].as_f64() +} + +/// `contract` met: the route chosen and the reasoning, or the refusal. +pub fn decide(reg: &Registry, v: &Value, host: &Host<'_>) -> Result { + let c = consider(reg, v, host)?; + if let Some(e) = c.refusal { + return Err(e); + } + let name = c.reasoning["choice"].as_str().unwrap_or("").to_string(); + let choice = match (c.plan, name.strip_prefix("provider:")) { + (Some(p), _) => Choice::Local(p), + (None, Some(n)) => Choice::Provider(n.to_string()), + (None, None) => return Err(format!("internal: the planner chose {name} and has no plan for it")), + }; + Ok(Decision { choice, reasoning: c.reasoning }) +} + +/// The plan of a contract job on a host that reaches no provider. +pub(crate) fn plan_in(reg: &Registry, v: &Value, job_bytes: u64) -> Result { + match decide(reg, v, &Host::new(job_bytes))?.choice { + Choice::Local(p) => Ok(p), + Choice::Provider(name) => Err(format!("internal: the planner chose the provider {name} with none brought")), + } +} + +/// A contract job's plan as the plan surfaces give it: the plan, with the +/// reasoning under `planner`, or the refusal. +pub fn plan_value(reg: &Registry, v: &Value, job_bytes: u64) -> Result { + plan_value_on(reg, v, &Host::new(job_bytes)) +} + +/// [`plan_value`] on `host`: its bound on a plan's energy, where it has one. +pub fn plan_value_on(reg: &Registry, v: &Value, host: &Host<'_>) -> Result { + let d = decide(reg, v, host)?; + let Choice::Local(p) = d.choice else { return Err("internal: a provider chosen with none brought".to_string()) }; + let mut o = serde_json::to_value(&p).map_err(|e| e.to_string())?; + o["planner"] = d.reasoning; + Ok(o) +} + +/// A contract job's plan and its result, carrying the reasoning: what a host +/// that runs a job in its own process does. +pub fn plan_and_run_in(reg: &Registry, v: &Value, host: &Host<'_>) -> Result<(Plan, Value), String> { + let d = decide(reg, v, host)?; + match d.choice { + Choice::Local(p) => { + let result = run_chosen(reg, v, &p, &d.reasoning)?; + own_check(v, &result)?; + Ok((p, result)) + } + Choice::Provider(name) => Err(format!("this job's contract is met by the provider {name}; a host that reaches it runs it there")), + } +} + +/// The route chosen run here, its result completed with `reasoning`. A result +/// that states no `elapsed_ms` of its own, so that its bits are the same on every +/// host (a device target's, a pulse program's), has the host's time of the run +/// in what it kept: a deadline is reported kept or missed all the same. +pub fn run_chosen(reg: &Registry, v: &Value, p: &Plan, reasoning: &Value) -> Result { + let began = std::time::Instant::now(); + let mut result = reg.run(v, p)?; + let ms = u64::try_from(began.elapsed().as_millis()).unwrap_or(u64::MAX); + complete(&mut result, reasoning)?; + if result.get("elapsed_ms").is_none() { + finish(v, &mut result, Some(ms)); + } + Ok(result) +} + +/// A run stopped at its contract's `max_joules`, by what read it. +#[derive(Clone, Debug, PartialEq)] +pub struct Stopped { + /// What the reading had come to when it stopped the run. + pub joules: f64, + pub elapsed_ms: u64, + /// What read it, and what that covers. + pub read: String, +} + +/// The result of a run stopped at its ceiling, not yet sealed: no answer, what +/// stopped it, and the reasoning, for a receipt that says so. +pub fn stopped_result(reg: &Registry, v: &Value, p: &Plan, reasoning: &Value, s: &Stopped) -> Value { + let gates = catalog::read_in(reg, v).map_or(0, |(r, _)| r.program.ops.len()); + let ceiling = Contract::read(v).ok().flatten().and_then(|c| c.max_joules); + let mut r = json!({ + "method": p.method, + "qubits": p.qubits, + "gates": gates, + "accuracy": { "class": STOPPED_CLASS, "note": "the run was stopped at its contract's energy ceiling, before it gave an answer" }, + "stopped": { "at": "max_joules", "joules": s.joules, "max_joules": ceiling, "elapsed_ms": s.elapsed_ms, "read": s.read }, + "elapsed_ms": s.elapsed_ms, + "planner": reasoning, + }); + super::schema::stamp(&mut r); + finish(v, &mut r, Some(s.elapsed_ms)); + r +} + +/// What a job's `contract` takes, as its committed schema has it: for the tool +/// lists. +pub fn contract_schema() -> Value { + let text = super::schema::FILES.iter().find(|(n, _)| *n == "job-request.v1.json").map_or("{}", |(_, t)| *t); + serde_json::from_str::(text).ok().and_then(|v| v.pointer("/properties/contract").cloned()).unwrap_or_else(|| json!({ "type": "object" })) +} + +/// `reasoning` in `result`, the result held first to the class the reasoning +/// wants, whether the contract named it or the job keeps what it would have had: +/// a method that gave less gives no answer ([`refusal::CLASS_BROKEN`]), since +/// its receipt would break section 8.7. An approximate simulator's counts fall +/// short only of a `simulated` the contract names. +pub fn complete(result: &mut Value, reasoning: &Value) -> Result<(), String> { + if result.get("stopped").is_some() { + result["planner"] = reasoning.clone(); + return Ok(()); + } + if let Some(wanted) = reasoning["wanted"].as_str() { + let got = result.pointer("/accuracy/class").and_then(Value::as_str).unwrap_or(""); + let approximate = result.pointer("/accuracy/approximate") == Some(&Value::Bool(true)) && reasoning["wanted_from"] == "contract"; + if !meets(wanted, got) || (wanted == "simulated" && approximate) { + let why = if approximate && wanted == "simulated" { "an approximate simulator's".to_string() } else { format!("{got:?}") }; + return Err(tag(refusal::CLASS_BROKEN, format!("the route {} gave a result of class {why}, and the job wants {wanted}: nothing it gave is returned", reasoning["choice"].as_str().unwrap_or("?")))); + } + } + result["planner"] = reasoning.clone(); + Ok(()) +} + +/// A contract job's result held to section 8.7 before a host seals it, as its +/// verifier will hold it once sealed: a host gives no receipt its own verifier +/// would refuse. What it kept is stated as [`finish`] states it. +pub fn own_check(v: &Value, result: &Value) -> Result<(), String> { + let mut r = result.clone(); + if r.get("planner").is_some() && r["planner"].get("kept").is_none() { + finish(v, &mut r, None); + } + let broken = check(v, &r); + if broken.is_empty() { + return Ok(()); + } + Err(format!("internal: no receipt is given: this host's verifier would refuse its reasoning ({})", broken.join(", "))) +} + +/// A provider's route held to section 8.7 before anything is sent: whatever a +/// receipt of this reasoning cannot give should cost nothing. The reasoning, +/// with a result that says only that the provider ran. +pub fn before_sending(v: &Value, reasoning: &Value, provider: &str, shots: u64) -> Result<(), String> { + let mut r = json!({ "method": "provider", "provider": { "name": provider }, "shots": shots, "counts_source": "shots", "execution": {}, "planner": reasoning, "shadow": { "ran": false, "code": "failed", "why": "not yet run" } }); + // What the run would seal of who ran it and what it costs: the route's own word. + let name = format!("provider:{provider}"); + if let Some(route) = reasoning["routes"].as_array().and_then(|a| a.iter().find(|x| x["route"] == name)) { + for k in ["device", "provenance"] { + if let Some(v) = route.get(k) { + r["provider"][k] = v.clone(); + } + } + let money = &route["price"]["money"]; + let mut estimate = json!({ "free": money["free"] }); + for k in ["amount", "currency", "unit", "at_least"] { + if let Some(v) = money.get(k) { + estimate[k] = v.clone(); + } + } + r["cost"] = json!({ "free": money["free"], "estimate": estimate }); + } + if reasoning["shadow"]["route"].is_null() { + r["shadow"]["code"] = reasoning["shadow"]["code"].clone(); + } + r["planner"]["kept"] = json!({}); + finish(v, &mut r, None); + let broken: Vec<&str> = check(v, &r).into_iter().filter(|c| !matches!(*c, CONTRACT_CLASS | PLANNER_KEPT)).collect(); + if broken.is_empty() { + return Ok(()); + } + Err(format!("internal: nothing was sent: this host's verifier would refuse its reasoning ({})", broken.join(", "))) +} + +/// A result's class held to the contract once it has run: a method that gave +/// less than the job wants gives no answer ([`refusal::CLASS_BROKEN`]). What the +/// run is held to here is the class the contract names; `check` also holds a +/// sealed result to the class it kept. +pub(crate) fn hold_class(v: &Value, result: &Value) -> Result<(), String> { + let Some(contract) = Contract::read(v)? else { return Ok(()) }; + let Some(wanted) = contract.exactness else { return Ok(()) }; + let got = result.pointer("/accuracy/class").and_then(Value::as_str).unwrap_or(""); + if !meets(&wanted, got) { + return Err(tag(refusal::CLASS_BROKEN, format!("the method {} gave a result of class {got:?}, and the contract wants {wanted}: nothing it gave is returned", result["method"].as_str().unwrap_or("?")))); + } + Ok(()) +} + +/// What the contract asked, against what happened: the deadline against the +/// time it took (`elapsed_ms`, else the result's own), the energy ceiling against +/// the result's figure, and the cost ceiling against what was charged. A result +/// that missed one is sealed and says so; one that cannot say says `null`. Done +/// when the result is complete, before it is sealed. +pub fn finish(v: &Value, result: &mut Value, elapsed_ms: Option) { + let Ok(Some(c)) = Contract::read(v) else { return }; + if result.get("planner").is_none() { + return; + } + let mut kept = Map::new(); + if let Some(d) = c.deadline_seconds { + let e = elapsed_ms.or_else(|| result.get("elapsed_ms").and_then(Value::as_u64)).or_else(|| result.pointer("/planner/kept/deadline/elapsed_ms").and_then(Value::as_u64)); + kept.insert("deadline".into(), json!({ "seconds": d, "elapsed_ms": e, "kept": e.map(|e| e as f64 <= d * 1000.0) })); + } + if let Some(j) = c.max_joules { + let stopped = result.pointer("/stopped/joules").and_then(Value::as_f64); + let x = stopped.or_else(|| result.pointer("/energy/joules_micro").and_then(Value::as_f64).map(|u| u / 1e6)); + kept.insert("energy".into(), json!({ "max_joules": j, "joules": x, "kept": if stopped.is_some() { Some(false) } else { x.map(|x| x <= j) } })); + } + if let Some((amount, currency)) = &c.max_cost { + let charged = result.pointer("/cost/charged").filter(|x| !x.is_null()).cloned(); + let free = result.pointer("/cost/free").is_none_or(|f| f == true); + let held = match (&charged, free) { + (Some(x), _) => x["amount"].as_str().filter(|a| is_decimal(a) && x["currency"] == currency.as_str()).map(|a| decimal_cmp(a, amount) != Ordering::Greater), + (None, true) => Some(true), + (None, false) => None, + }; + kept.insert("cost".into(), json!({ "max_cost": { "amount": amount, "currency": currency }, "charged": charged, "kept": held })); + } + result["planner"]["kept"] = Value::Object(kept); +} + +/// Whether anything the contract asked was missed, as the result says. +pub fn missed(result: &Value) -> bool { + result.pointer("/planner/kept").and_then(Value::as_object).is_some_and(|k| k.values().any(|x| x["kept"] == false)) +} + +/// The deadline a contract job's provider run is held to, from its submission, +/// in milliseconds, where its contract gives one. +pub fn deadline_ms(v: &Value) -> Option { + Contract::read(v).ok().flatten().and_then(|c| c.deadline_seconds).map(|d| d * 1000.0) +} + +// --------------------------------------------------------------------------- +// The shadow +// --------------------------------------------------------------------------- + +/// The seed a job's shadow samples with. +pub fn shadow_seed(v: &Value) -> u64 { + let seed = v.get("seed").and_then(Value::as_u64).unwrap_or(1); + ((u128::from(seed) + u128::from(SHADOW_SEED_OFFSET)) % (1 << 53)) as u64 +} + +/// What the contract leaves a shadow, in seconds: the deadline less the +/// provider's own time, never below 0; the deadline where the provider states +/// no time; [`SHADOW_MAX_SECONDS`] with no deadline. +fn shadow_budget(contract: &Contract, provider_seconds: Option) -> f64 { + match (contract.deadline_seconds, provider_seconds) { + (Some(d), Some(s)) => (d - s).max(0.0), + (Some(d), None) => d, + (None, _) => SHADOW_MAX_SECONDS, + } +} + +/// The request a shadow of `v` runs: its program and shots on a seed of its own, +/// and nothing else. None for a job that does not read as a provider's. +fn shadow_request(v: &Value) -> Option { + let read = super::provider::read_named(v, Some("shadow")).ok()?; + Some(json!({ "qasm": v.get("qasm").cloned().unwrap_or(Value::Null), "shots": read.shots, "seed": shadow_seed(v) })) +} + +/// The classical method that can reach the provider's counts within the +/// contract, the most exact first and then the cheapest, or why none can: what +/// the contract leaves after the provider's own time, or [`SHADOW_MAX_SECONDS`]. +fn shadow_plan(reg: &Registry, v: &Value, host: &Host<'_>, contract: &Contract, provider_seconds: Option) -> Value { + let budget = shadow_budget(contract, provider_seconds); + let Some(mut req) = shadow_request(v) else { + return json!({ "route": null, "code": "none", "why": "the job does not read as a provider job" }); + }; + let auto = match catalog::read_in(reg, &req) { + Ok(a) => a, + Err(e) => return json!({ "route": null, "code": "none", "why": e }), + }; + let mut candidates: Vec = Vec::new(); + let mut tried: Vec = Vec::new(); + { + let (r, uses) = (&auto.0, &auto.1); + let job = Job::new(reg, &req, host.job_bytes, Some(r), uses); + for m in reg.methods().filter(|m| !m.reads_program()) { + let route = format!("method:{}", m.name()); + match catalog::plan_one(m, &job) { + Err(e) => tried.push(json!({ "route": route, "code": "none", "why": e })), + Ok(p) if p.memory_bytes > host.job_bytes => tried.push(json!({ "route": route, "code": "memory", "why": format!("it takes {} bytes, and a job here takes at most {}", p.memory_bytes, host.job_bytes) })), + Ok(p) => { + let priced = local_route(m, reg.identity(Kind::Method, m.name()), Some(r), Some(&p), host, false, None); + match priced["price"]["time"]["seconds"].as_f64() { + Some(s) if s <= budget => candidates.push(priced), + Some(s) => tried.push(json!({ "route": route, "code": "budget", "why": format!("about {s} s, and the contract leaves a shadow {budget} s") })), + None => tried.push(json!({ "route": route, "code": "budget", "why": "its time is not known" })), + } + } + } + } + } + candidates.sort_by(|a, b| strength(a["class"].as_str().unwrap_or("")).cmp(&strength(b["class"].as_str().unwrap_or(""))).then_with(|| cheaper(a, b))); + let Some(best) = candidates.into_iter().next() else { + let has = |c: &str| tried.iter().any(|t| t["code"] == c); + let code = if has("budget") { "budget" } else if has("memory") { "memory" } else { "none" }; + let why = match code { + "budget" => format!("a classical method could reach these counts, but not in the {budget} s the contract leaves a shadow"), + "memory" => "a classical method could reach these counts, but not in a job's memory here".to_string(), + _ => "no classical method here takes this program".to_string(), + }; + return json!({ "route": null, "code": code, "why": why, "tried": tried }); + }; + req["method"] = best["method"].clone(); + json!({ "route": best["route"], "class": best["class"], "request": req, "budget_seconds": budget, "price": best["price"] }) +} + +/// The distance between two lists of counts of the same shots, recomputable +/// from them: the total variation exactly, as whole numbers, the Hellinger +/// fidelity, and a bound on the total variation the shots alone would leave +/// between two samples of one distribution, each in a fixed order of outcomes +/// (section 8.7). `None` with no shots, or counts past them. +/// +/// The bound: given each outcome's count n in both lists together, the two +/// lists' difference on it, were both samples of one distribution, is at most +/// what a fair coin's split of n leaves on average, E|2B − n| with B binomial +/// (n, ½) ([`split_mad`]): a list of S shots exactly splits tighter. Half their +/// sum over S, and at most 1, bounds the total variation the shots alone leave, +/// for every number of outcomes and shots, sparse or dense. +pub fn distance(a: &Value, b: &Value, shots: u64) -> Option { + let (a, b) = (a.as_object()?, b.as_object()?); + if shots == 0 { + return None; + } + let mut keys: Vec<&String> = a.keys().chain(b.keys()).collect(); + keys.sort_by(|x, y| x.as_bytes().cmp(y.as_bytes())); + keys.dedup(); + let s = shots as f64; + // Sums of whole numbers are exact; each product and quotient is a double's. + let (mut numerator, mut root, mut bound, mut total) = (0u128, 0.0f64, 0.0f64, 0u128); + for k in keys { + let x = a.get(k).and_then(Value::as_u64).unwrap_or(0); + let y = b.get(k).and_then(Value::as_u64).unwrap_or(0); + numerator += u128::from(x.abs_diff(y)); + root += ((x as f64) * (y as f64)).sqrt(); + let n = u128::from(x) + u128::from(y); + total += n; + bound += split_mad(n); + } + // Counts past the shots are not two lists of them. + if total > 2 * u128::from(shots) { + return None; + } + let denominator = 2 * u128::from(shots); + let whole = |x: u128| if x < (1 << 53) { json!(x as u64) } else { json!(x as f64) }; + Some(json!({ + "computed": true, + "numerator": whole(numerator), + "denominator": whole(denominator), + "total_variation": numerator as f64 / denominator as f64, + "hellinger_fidelity": root * root / (s * s), + "sampling_tvd_bound": (0.5 * bound / s).min(1.0), + })) +} + +/// E|2B − n| for B binomial (n, ½): what a fair coin's split of n leaves +/// between its two sides, on average. It is the same for n = 2j + 1 and +/// 2j + 2, and is the product of (2i + 3) ÷ (2i + 2) for i from 0 to j − 1, +/// taken in that order; from j = 4096 on, (2j + 1)·(1 − 1/8j + 1/128j² + +/// 5/1024j³) ÷ √(πj), within 3·10⁻¹⁵ of it there. Only `× ÷ + −` and `√`, in +/// IEEE 754 doubles in the order written, so every verifier gets the same bits. +pub fn split_mad(n: u128) -> f64 { + if n == 0 { + return 0.0; + } + let j = (n - 1) / 2; + if j < 4096 { + let mut m = 1.0f64; + for i in 0..j as u32 { + m = m * f64::from(2 * i + 3) / f64::from(2 * i + 2); + } + return m; + } + let jj = j as f64; + let c = (1.0 - 1.0 / (8.0 * jj) + 1.0 / (128.0 * jj * jj) + 5.0 / (1024.0 * jj * jj * jj)) / (std::f64::consts::PI * jj).sqrt(); + (2.0 * jj + 1.0) * c +} + +/// A provider's result, with the shadow the reasoning planned run beside it: a +/// result's `shadow`, carrying both counts' distance, or why there is none. +pub fn shadow(reg: &Registry, reasoning: &Value, result: &Value) -> Value { + let plan = &reasoning["shadow"]; + if plan["route"].is_null() { + return json!({ "ran": false, "code": plan["code"], "why": plan["why"] }); + } + let req = &plan["request"]; + let job_bytes = reasoning["host"]["job_bytes"].as_u64().unwrap_or(u64::MAX); + let run = catalog::plan_plain(reg, req, job_bytes).and_then(|p| reg.run(req, &p)); + let out = match run { + Ok(o) => o, + Err(e) => return json!({ "ran": false, "code": "failed", "why": e }), + }; + let shots = result.get("shots").and_then(Value::as_u64).unwrap_or(0); + let whole_lists = result["omitted_shots"].as_f64() == Some(0.0) && out["omitted_shots"].as_f64() == Some(0.0); + let distance = if whole_lists { + distance(&result["counts"], &out["counts"], shots).unwrap_or_else(|| json!({ "computed": false, "why": "the counts give no distance: no shots, or a list that is not of its form" })) + } else { + json!({ "computed": false, "why": "a list of counts leaves out shots, so the distance is not known from them" }) + }; + let mut s = json!({ + "ran": true, + "route": plan["route"], + "accuracy": out["accuracy"], + "request": req, + "shots": shots, + "counts": out["counts"], + "distinct_outcomes": out["distinct_outcomes"], + "omitted_shots": out["omitted_shots"], + "distance": distance, + }); + if let Some(e) = out.get("elapsed_ms") { + s["elapsed_ms"] = e.clone(); + } + s +} + +/// A provider's contract job's result made complete: the reasoning, the shadow +/// and what the contract kept. What the job took, from its submission, is the +/// host's to say. A result whose class is not what the job wants (its device +/// said another provenance when it ran) gives no answer. +pub fn seal_provider(reg: &Registry, v: &Value, result: &mut Value, reasoning: &Value, elapsed_ms: Option) -> Result<(), String> { + complete(result, reasoning)?; + result["shadow"] = shadow(reg, reasoning, result); + finish(v, result, elapsed_ms); + Ok(()) +} + +// --------------------------------------------------------------------------- +// What a verifier holds a sealed result to (section 8.7) +// --------------------------------------------------------------------------- + +fn is_whole(v: &Value) -> bool { + v.as_f64().is_some_and(|x| x.fract() == 0.0 && x >= 0.0) +} + +/// A number of seconds a price may state: at least 0 and at most +/// [`MAX_SECONDS`]. +fn seconds_ok(v: &Value) -> bool { + v.as_f64().is_some_and(|s| (0.0..=MAX_SECONDS).contains(&s)) +} + +/// Exactly these members. +fn has_exactly(v: &Value, keys: &[&str]) -> bool { + v.as_object().is_some_and(|o| o.len() == keys.len() && keys.iter().all(|k| o.contains_key(*k))) +} + +fn price_form(p: &Value, local: bool) -> bool { + let m = &p["money"]; + let amount_ok = m.get("amount").is_none_or(|a| a.as_str().is_some_and(|a| a.chars().count() <= MAX_AMOUNT)); + let money_ok = match m["free"].as_bool() { + Some(true) => true, + // A local route's money is free: only a provider's costs. + Some(false) => !local && (m["unknown"].is_string() || (m["amount"].is_string() && m["currency"].is_string())), + None => false, + } && m.get("at_least").is_none_or(|x| *x == Value::Bool(true)) + && amount_ok; + let time_ok = p["time"].is_object() && (p["time"]["seconds"].is_null() || seconds_ok(&p["time"]["seconds"])); + let energy_ok = p["energy"].is_object() && (p["energy"]["joules"].is_null() || p["energy"]["joules"].is_number()) && ["watch", "unwatched"].iter().all(|k| p["energy"].get(*k).is_none_or(Value::is_string)) && (p["energy"].get("watch").is_none() || p["energy"].get("unwatched").is_none()); + let left_ok = p["leaves_out"].as_array().is_some_and(|a| a.iter().all(|w| w.as_str().is_some_and(|w| LEFT_OUT.contains(&w)))); + // A method's are whole numbers, and a provider's `null`: it states neither. + let counted = ["memory_bytes", "work"].iter().all(|k| p.get(*k).is_some_and(|x| if local { is_whole(x) } else { x.is_null() })); + money_ok && time_ok && energy_ok && left_ok && counted +} + +fn route_form(r: &Value) -> bool { + let Some(name) = r["route"].as_str() else { return false }; + let kind = r["kind"].as_str(); + let local = name.strip_prefix("method:").is_some_and(|m| !m.is_empty()) && kind == Some("local"); + let kind_ok = local || (name.strip_prefix("provider:").is_some_and(|m| !m.is_empty()) && kind == Some("provider")); + let outcome_ok = match r["outcome"].as_str() { + Some("chosen" | "met") => r.get("rejected").is_none(), + Some("rejected") => r["rejected"]["code"].is_string() && r["rejected"]["why"].is_string(), + _ => false, + }; + let price_ok = match r.get("price") { + Some(Value::Null) => true, + Some(p) if p.is_object() => price_form(p, local), + _ => false, + }; + // A local route states its rank in auto's order for the job's question. + let rank_ok = !local || r.get("auto_rank").is_some_and(|k| k.is_null() || is_whole(k)); + kind_ok && outcome_ok && price_ok && rank_ok && r["class"].is_string() && r["host_dependent"].is_boolean() +} + +fn planner_form(p: &Value) -> bool { + let wanted_ok = p["wanted"].is_null() || p["wanted"].is_string(); + let from_ok = match p.get("wanted_from") { + Some(Value::String(s)) => ["contract", "named", "auto"].contains(&s.as_str()), + Some(Value::Null) => p["wanted"].is_null(), + _ => false, + }; + let Some(routes) = p["routes"].as_array().filter(|a| !a.is_empty()) else { return false }; + let mut names: Vec<&str> = routes.iter().filter_map(|r| r["route"].as_str()).collect(); + let n = names.len(); + names.sort_unstable(); + names.dedup(); + let listed = |x: &Value| x.as_str().is_some_and(|s| routes.iter().any(|r| r["route"] == s)); + p["format"] == FORMAT + && wanted_ok + && from_ok + && (p["named"].is_null() || listed(&p["named"])) + && p["question"].as_str().is_some_and(|q| QUESTIONS.contains(&q)) + && (p["auto"].is_null() || listed(&p["auto"])) + && is_whole(&p["host"]["job_bytes"]) + && p["host"]["providers"].as_array().is_some_and(|a| a.iter().all(Value::is_string)) + && names.len() == n + && n == routes.len() + && routes.iter().all(route_form) + && listed(&p["choice"]) + && p["why"].is_string() + && p["stable"].is_object() + && p["kept"].is_object() +} + +/// What is wrong with a sealed result's reasoning (section 8.7): nothing, for a +/// job with no contract and no reasoning. `method` here is the result's, so a +/// route is held to what ran. +pub fn check(request: &Value, result: &Value) -> Vec<&'static str> { + let planner = result.get("planner"); + let contract = match Contract::read(request) { + Ok(Some(c)) => c, + Ok(None) => { + let mut out = Vec::new(); + if planner.is_some() { + out.push(PLANNER_FORM); + } + if result.get("shadow").is_some() { + out.push(SHADOW); + } + if result.get("stopped").is_some() { + out.push(STOPPED); + } + return out; + } + Err(_) => return vec![CONTRACT_FORM], + }; + let Some(p) = planner.filter(|p| planner_form(p)) else { return vec![PLANNER_FORM] }; + let mut out = Vec::new(); + // Under a contract a provider is used only where it allows one. + if request.get("provider").is_some_and(|x| !x.is_null()) && contract.providers != Some(true) { + out.push(CONTRACT_PROVIDER); + } + let routes = p["routes"].as_array().map_or(&[][..], Vec::as_slice); + // The providers the host brought are its provider routes, in their order. + let brought: Vec<&str> = routes.iter().filter(|r| r["kind"] == "provider").filter_map(|r| r["route"].as_str()?.strip_prefix("provider:")).collect(); + if p["host"]["providers"].as_array().is_none_or(|a| a.iter().map(Value::as_str).ne(brought.iter().map(|b| Some(*b)))) { + out.push(PLANNER_FORM); + return out; + } + // What the job names, the question it asks and what auto picks, each from + // the request and the routes, never from what the reasoning says of itself. + let named = match request_names(request) { + Some(n) => Some(n), + // A device target's job runs on the method its noise takes, as stated. + None if names_target(request) => p["named"].as_str().filter(|n| n.starts_with("method:")).map(str::to_string), + None => None, + }; + let q = question_of(request); + let ranks_ok = routes.iter().filter(|r| r["kind"] == "local").all(|r| { + let m = r["route"].as_str().and_then(|n| n.strip_prefix("method:")).unwrap_or(""); + declared(m).is_none_or(|b| r["auto_rank"].as_f64() == b.auto_rank(question(q)).map(f64::from)) + }); + let auto = auto_of(routes, request, named.as_deref()); + let class_named = |name: &str| routes.iter().find(|r| r["route"] == name).and_then(|r| r["class"].as_str()).map(str::to_string); + let (wanted, from) = match (&contract.exactness, &named, &auto) { + (Some(w), ..) => (Some(w.clone()), Some("contract")), + (None, Some(n), _) => (class_named(n), Some("named")), + (None, None, Some(a)) => (class_named(a), Some("auto")), + (None, None, None) => (None, None), + }; + if p["named"].as_str() != named.as_deref() || p["question"] != q || !ranks_ok || p["auto"].as_str() != auto.as_deref() || p["wanted"].as_str() != wanted.as_deref() || p["wanted_from"].as_str() != from { + out.push(PLANNER_FORM); + return out; + } + let held = Held { contract: &contract, named: named.as_deref(), fabric: fab_of(request), wanted: wanted.as_deref(), from_contract: from == Some("contract"), job_bytes: p["host"]["job_bytes"].as_f64().unwrap_or(0.0) }; + let mut route_broken = false; + let mut choice = None; + for r in routes { + if r["outcome"] == "chosen" { + if choice.is_some() { + route_broken = true; + } + choice = r["route"].as_str(); + } + if r["rejected"]["code"].as_str() != gate(r, &held) || !states_itself(r, request) { + route_broken = true; + } + } + if route_broken || choice != p["choice"].as_str() { + out.push(PLANNER_ROUTE); + } + let picked = pick(routes, auto.as_deref(), &held); + let ran = if result["method"] == "provider" { result.pointer("/provider/name").and_then(Value::as_str).map(|n| format!("provider:{n}")) } else { result["method"].as_str().map(|m| format!("method:{m}")) }; + if picked.and_then(|r| r["route"].as_str()) != p["choice"].as_str() || ran.as_deref() != p["choice"].as_str() || !ran_as_routed(routes, p["choice"].as_str(), result) { + out.push(PLANNER_CHOICE); + } + let want_stable = stable_of(routes, &p["host"]["job_bytes"], p["choice"].as_str(), &contract); + if ["routes", "digest", "choice"].iter().any(|k| p["stable"].get(*k) != want_stable.get(*k)) { + out.push(PLANNER_STABLE); + } + if !kept_holds(&contract, p, result) { + out.push(PLANNER_KEPT); + } + let class = result.pointer("/accuracy/class").and_then(Value::as_str).unwrap_or(""); + let approximate = result.pointer("/accuracy/approximate") == Some(&Value::Bool(true)); + let short = wanted.as_deref().is_some_and(|w| !meets(w, class) || (from == Some("contract") && w == "simulated" && approximate)); + // A method's result has a class its method has. A run stopped at its ceiling + // gave no answer, and has none. + let foreign = result["method"].as_str().filter(|m| *m != "provider").is_some_and(|m| !class_of_method(m, class)); + if result.get("stopped").is_some() { + if !stopped_holds(&contract, result) { + out.push(STOPPED); + } + } else if short || foreign { + out.push(CONTRACT_CLASS); + } + // Under a contract a provider's result is of the current form: the earlier one + // states neither where its counts come from nor what was done to them. + if result["method"] == "provider" && (result.get("counts_source").is_none() || result.get("execution").is_none()) { + out.push(CONTRACT_FORM); + } + let is_provider = p["choice"].as_str().is_some_and(|c| c.starts_with("provider:")); + if is_provider != result.get("shadow").is_some() || is_provider != p.get("shadow").is_some() || (is_provider && !shadow_holds(request, &contract, p, result)) { + out.push(SHADOW); + } + out +} + +/// Whether `class` is one the built-in `method` has; any class of a method that +/// is not one of the built-ins, whose word it is. Like every rule [`check`] +/// reads of a built-in, from its declaration ([`declared`]), never its code. +fn class_of_method(method: &str, class: &str) -> bool { + declared(method).is_none_or(|m| m.classes.contains(&class)) +} + +/// Whether a route states of itself what section 8.7 gives it. A built-in method +/// has the class its table gives it, on `request`, and depends on the host only +/// when it runs on a GPU; a provider's route depends on the host. +fn states_itself(r: &Value, request: &Value) -> bool { + let class = r["class"].as_str().unwrap_or(""); + // A provider's route has the class its provenance gives. + let Some(m) = r["route"].as_str().and_then(|n| n.strip_prefix("method:")) else { + return r["host_dependent"] == true && r["provenance"].as_str().and_then(super::provider::class_of_provenance).is_none_or(|c| class == c); + }; + // A method the host registered is the host's own code. + let Some(builtin) = declared(m) else { + return r["host_dependent"] == true; + }; + let given = |k: &str| request["options"].get(k).is_some_and(|x| !x.is_null()); + let by_job = match m { + "stabilizer" => class == if request.get("noise").is_some_and(|x| !x.is_null()) || crate::engine::targets::job::names_target(request) { "estimate" } else { "exact" }, + "stabilizer_rank" => class == if given("terms") || given("epsilon") { "estimate" } else { "exact" }, + // Its plan says which table fits, and a route need not be priced. + "cutrank" => true, + // Every other method's route has the one class its table gives: the first + // each class it declares meets. + _ => class == worst_of(builtin.classes), + }; + by_job && class_of_method(m, class) && r["host_dependent"] == is_gpu(m) +} + +/// The members a stopped run's result has, and no other: it gave no answer of any kind. +const STOPPED_MEMBERS: [&str; 11] = ["method", "qubits", "gates", "accuracy", "stopped", "elapsed_ms", "planner", "energy", "engine", "schema", "receipt"]; + +/// Whether a run stopped at its ceiling says so of its form: on a contract that +/// gives one, a reading at or past it, on a method's run, with no answer. +fn stopped_holds(c: &Contract, result: &Value) -> bool { + let s = &result["stopped"]; + has_exactly(s, &["at", "joules", "max_joules", "elapsed_ms", "read"]) + && s["at"] == "max_joules" + && c.max_joules.is_some_and(|j| s["max_joules"].as_f64() == Some(j) && s["joules"].as_f64().is_some_and(|x| x >= j)) + && is_whole(&s["elapsed_ms"]) + && s["read"].is_string() + && result["method"] != "provider" + && result.pointer("/accuracy/class").and_then(Value::as_str) == Some(STOPPED_CLASS) + && result.as_object().is_some_and(|o| o.keys().all(|k| STOPPED_MEMBERS.contains(&k.as_str()))) + // Its whole figure, where it has one, is no less than what stopped it, and + // its time is the result's. + && result.pointer("/energy/joules_micro").and_then(Value::as_f64).is_none_or(|u| s["joules"].as_f64().is_some_and(|j| u >= j * 1e6 - 1.0)) + && result["elapsed_ms"].as_f64() == s["elapsed_ms"].as_f64() +} + +/// Whether the route chosen is what ran: for a provider's, the result's provider +/// is the device and provenance it names, where it names them, and the result's +/// cost is its money (free alike, and its amount, currency, unit and whether it +/// is the least it can come to). +fn ran_as_routed(routes: &[Value], choice: Option<&str>, result: &Value) -> bool { + let Some(r) = routes.iter().find(|r| r["route"].as_str() == choice) else { return true }; + if r["kind"] != "provider" { + return true; + } + let (money, cost) = (&r["price"]["money"], &result["cost"]); + ["device", "provenance"].iter().all(|k| r.get(*k).is_none_or(|v| alike(Some(v), result["provider"].get(*k)))) + && alike(cost.get("free"), money.get("free")) + && ["amount", "currency", "unit", "at_least"].iter().all(|k| alike(cost["estimate"].get(*k), money.get(*k))) +} + +/// Two members alike as section 8.7 compares them: numbers by value (7 and 7.0, +/// -0 and 0 alike), a boolean only to a boolean, and `null` as an absent member. +fn alike(a: Option<&Value>, b: Option<&Value>) -> bool { + let a = a.filter(|v| !v.is_null()); + let b = b.filter(|v| !v.is_null()); + match (a, b) { + (None, None) => true, + (Some(Value::Number(x)), Some(Value::Number(y))) => x.as_f64() == y.as_f64(), + (Some(Value::Number(_)), _) | (_, Some(Value::Number(_))) => false, + // Lists and objects member by member, by the same rule. + (Some(Value::Array(x)), Some(Value::Array(y))) => x.len() == y.len() && x.iter().zip(y).all(|(a, b)| alike(Some(a), Some(b))), + (Some(Value::Object(x)), Some(Value::Object(y))) => { + x.keys().chain(y.keys()).all(|k| alike(x.get(k), y.get(k))) + } + (Some(x), Some(y)) => x == y, + _ => false, + } +} + +/// A `kept` member as its table gives it: true, false, or `null` where it is not +/// known. Nothing else reads as `null`. +fn kept_is(v: &Value, want: Option) -> bool { + want.map_or(v.is_null(), |b| *v == Value::Bool(b)) +} + +/// Whether a sealed `kept` is what the contract and the result give: exactly a +/// member for each the contract gives, each of exactly its members. +fn kept_holds(c: &Contract, p: &Value, result: &Value) -> bool { + let kept = &p["kept"]; + let Some(k) = kept.as_object() else { return false }; + let asked = [("deadline", c.deadline_seconds.is_some()), ("energy", c.max_joules.is_some()), ("cost", c.max_cost.is_some())]; + if k.len() != asked.iter().filter(|(_, a)| *a).count() || !asked.iter().all(|(n, a)| kept.get(*n).is_some() == *a) { + return false; + } + if let Some(d) = c.deadline_seconds { + let e = &kept["deadline"]["elapsed_ms"]; + let want = e.as_f64().map(|e| e <= d * 1000.0); + // A local result's own elapsed_ms, by value, and null when it has none. + // A method's time is its result's, where its result states one. + let local_e = result["method"] != "provider" && result.get("elapsed_ms").is_some_and(|x| x.as_f64() != e.as_f64()); + if !has_exactly(&kept["deadline"], &["seconds", "elapsed_ms", "kept"]) || kept["deadline"]["seconds"].as_f64() != Some(d) || !(e.is_null() || is_whole(e)) || !kept_is(&kept["deadline"]["kept"], want) || local_e { + return false; + } + } + if let Some(j) = c.max_joules { + let stopped = result.pointer("/stopped/joules").and_then(Value::as_f64); + let x = stopped.or_else(|| result.pointer("/energy/joules_micro").and_then(Value::as_f64).map(|u| u / 1e6)); + let want = if stopped.is_some() { Some(false) } else { x.map(|x| x <= j) }; + if !has_exactly(&kept["energy"], &["max_joules", "joules", "kept"]) || kept["energy"]["max_joules"].as_f64() != Some(j) || kept["energy"]["joules"].as_f64() != x || !kept_is(&kept["energy"]["kept"], want) { + return false; + } + } + if let Some((amount, currency)) = &c.max_cost { + let charged = result.pointer("/cost/charged").filter(|x| !x.is_null()); + let free = result.pointer("/cost/free").is_none_or(|f| f == true); + let held = match (charged, free) { + (Some(x), _) => x["amount"].as_str().filter(|a| is_decimal(a) && x["currency"] == currency.as_str()).map(|a| decimal_cmp(a, amount) != Ordering::Greater), + (None, true) => Some(true), + (None, false) => None, + }; + let sealed = &kept["cost"]; + let charged_same = match charged { + Some(x) => same(&sealed["charged"], x), + None => sealed["charged"].is_null(), + }; + if !has_exactly(sealed, &["max_cost", "charged", "kept"]) || !has_exactly(&sealed["max_cost"], &["amount", "currency"]) || sealed["max_cost"]["amount"].as_str() != Some(amount.as_str()) || sealed["max_cost"]["currency"].as_str() != Some(currency.as_str()) || !kept_is(&sealed["kept"], held) || !charged_same { + return false; + } + } + true +} + +/// JSON equality with numbers by value (section 8.4: a number's spelling is not +/// sealed): `4` and `4.0` are one number. +fn same(a: &Value, b: &Value) -> bool { + match (a, b) { + (Value::Number(x), Value::Number(y)) => x.as_f64() == y.as_f64(), + (Value::Array(x), Value::Array(y)) => x.len() == y.len() && x.iter().zip(y).all(|(p, q)| same(p, q)), + (Value::Object(x), Value::Object(y)) => x.len() == y.len() && x.iter().all(|(k, v)| y.get(k).is_some_and(|w| same(v, w))), + _ => a == b, + } +} + +/// A count of a shadow's list: a whole number written as one, from 1 to 2^53 − 1. +fn count_of(v: &Value) -> Option { + v.as_u64().filter(|n| (1..1 << 53).contains(n)) +} + +/// Whether the reasoning's `shadow` is of its form: with no route, a code of +/// `budget`, `memory` or `none`; with one, a method's route, a class, the budget +/// the contract leaves, a price within it, and a request of exactly the +/// program, the shots, the shadow's seed and the method. +fn shadow_plan_holds(request: &Value, contract: &Contract, p: &Value, result: &Value) -> bool { + let plan = &p["shadow"]; + if plan.get("route").is_none() { + return false; + } + match plan["route"].as_str() { + None => plan["route"].is_null() && plan["code"].as_str().is_some_and(|c| ["budget", "memory", "none"].contains(&c)) && plan["why"].is_string() && plan.get("tried").is_none_or(Value::is_array), + Some(route) => { + let Some(method) = route.strip_prefix("method:").filter(|m| !m.is_empty()) else { return false }; + let chosen = p["choice"].as_str().unwrap_or(""); + let budget = shadow_budget(contract, provider_seconds(&p["routes"], chosen)); + let req = &plan["request"]; + let listed = p["routes"].as_array().and_then(|a| a.iter().find(|r| r["route"].as_str() == Some(route))); + plan["class"].as_str().is_some_and(|c| LADDER.contains(&c)) + && listed.is_some_and(|r| r["class"] == plan["class"]) + && plan["budget_seconds"].as_f64() == Some(budget) + && plan["price"].is_object() + && price_form(&plan["price"], true) + && plan["price"]["time"]["seconds"].as_f64().is_some_and(|s| s <= budget) + && has_exactly(req, &["qasm", "shots", "seed", "method"]) + && req["qasm"].is_string() + && req["qasm"] == request["qasm"] + && same(&req["shots"], &result["shots"]) + && req["seed"].as_u64() == Some(shadow_seed(request)) + && req["method"].as_str() == Some(method) + } + } +} + +/// Whether a shadow's outcomes are of a counts' form: each a string of `0` and +/// `1`, all of one width, and, with none omitted, as many as it says. +fn outcomes_hold(s: &Value, omitted: Option, of: &Value) -> bool { + let Some(counts) = s["counts"].as_object() else { return false }; + // As wide as the job's outcomes, where the provider's counts name one. + let width = of.as_object().and_then(|c| c.keys().next()).or_else(|| counts.keys().next()).map_or(0, String::len); + counts.keys().all(|k| k.len() == width && k.bytes().all(|b| b == b'0' || b == b'1')) && (omitted != Some(0) || s["distinct_outcomes"].as_f64() == Some(counts.len() as f64)) +} + +/// Whether a sealed shadow is of its form, what its plan says, and its distance +/// what its counts give. +fn shadow_holds(request: &Value, contract: &Contract, p: &Value, result: &Value) -> bool { + let (s, plan) = (&result["shadow"], &p["shadow"]); + if !shadow_plan_holds(request, contract, p, result) { + return false; + } + match s["ran"].as_bool() { + Some(false) => s["code"].is_string() && s["why"].is_string() && if plan["route"].is_null() { plan["code"] == s["code"] } else { s["code"] == "failed" }, + Some(true) => { + let Some(route) = plan["route"].as_str() else { return false }; + // The shots and the omitted shots by value; the counts whole, and an + // exact sum: no double between them. + let by_value = |v: &Value| v.as_f64().filter(|x| x.fract() == 0.0 && *x >= 0.0).map(|x| x as u64); + let shots = by_value(&result["shots"]); + let counts: Option> = s["counts"].as_object().and_then(|o| o.values().map(count_of).collect()); + let listed: Option = counts.map(|c| c.iter().map(|&n| u128::from(n)).sum()); + let omitted = by_value(&s["omitted_shots"]); + let counts_ok = match (listed, omitted, shots) { + (Some(l), Some(o), Some(n)) => l + u128::from(o) == u128::from(n), + _ => false, + } && is_whole(&s["distinct_outcomes"]) + && outcomes_hold(s, omitted, &result["counts"]); + let whole_lists = result["omitted_shots"].as_f64() == Some(0.0) && s["omitted_shots"].as_f64() == Some(0.0); + let distance_ok = match s["distance"]["computed"].as_bool() { + Some(false) => s["distance"]["why"].is_string() && !whole_lists, + Some(true) => { + whole_lists + && shots.and_then(|x| distance(&result["counts"], &s["counts"], x)).is_some_and(|d| { + ["numerator", "denominator", "total_variation", "hellinger_fidelity", "sampling_tvd_bound"].iter().all(|k| d[*k].as_f64() == s["distance"][*k].as_f64()) + }) + } + None => false, + }; + let method = route.strip_prefix("method:").unwrap_or(""); + let class_ok = s["accuracy"]["class"].as_str().is_some_and(|c| class_of_method(method, c) && plan["class"].as_str().is_some_and(|w| meets(w, c))); + counts_ok && distance_ok && class_ok && s["route"].as_str() == Some(route) && same(&s["request"], &plan["request"]) && same(&s["shots"], &result["shots"]) + } + None => false, + } +} + +/// What a verifier states of a contract job: the choice, the class wanted and +/// the class given, what was kept, and the shadow. +pub fn statement(result: &Value) -> Option { + let p = result.get("planner")?; + let s = &result["shadow"]; + Some(json!({ + "choice": p["choice"], + "wanted": p["wanted"], + "class": result.pointer("/accuracy/class"), + "stable_choice": p["stable"]["choice"], + "kept": p["kept"], + "shadow_ran": s["ran"], + "shadow_total_variation": s["distance"]["total_variation"], + })) +} + +/// What can be run again of a sealed contract job, by this engine: the local +/// routes priced again at the job's memory, held to the sealed digest, and the +/// route `auto` picks from them, held to the sealed one; and the shadow run +/// again, held to its counts bit for bit, or, where the host says it failed, +/// run to see whether it does. Nothing else is recomputed here: a provider's +/// counts cannot be, and a price the host stated is its word. +pub fn recheck(reg: &Registry, job: &Value) -> Result { + let (Some(request), Some(result)) = (job.get("request"), job.get("result")) else { + return Err("expected a job: {\"request\": ..., \"result\": ...}".into()); + }; + let Some(p) = result.get("planner") else { return Err("this result carries no planner's reasoning".into()) }; + let engine = result.pointer("/engine/version").and_then(Value::as_str); + let same_engine = engine == Some(super::schema::ENGINE_VERSION); + let job_bytes = p["host"]["job_bytes"].as_f64().filter(|x| x.fract() == 0.0 && *x >= 0.0 && *x < 1.8446744073709552e19).map(|x| x as u64).ok_or("the reasoning names no job memory")?; + let routes = p["routes"].as_array().map_or(&[][..], Vec::as_slice); + let priced = if request.get("provider").is_some_and(|x| !x.is_null()) { + json!({ "checked": false, "why": "the job names its provider, so no local route was priced" }) + } else { + let host = Host::new(job_bytes); + let local = local_routes(reg, request, &host, question(question_of(request)))?; + let digest = stable_of(&local.routes, &p["host"]["job_bytes"], None, &Contract::default())["digest"].clone(); + // What auto picks over the routes as this engine prices them, those that + // depend on the host as the sealing host stated them: a verifier here has + // neither its GPU nor its registered methods. + let mixed: Vec = routes.iter().filter(|r| r["kind"] == "local").map(|r| if r["host_dependent"] == false { local.routes.iter().find(|l| l["route"] == r["route"]).unwrap_or(r).clone() } else { r.clone() }).collect(); + let auto = auto_of(&mixed, request, local.named.as_deref()); + let auto_same = json!(auto) == p["auto"]; + let named_same = json!(local.named) == p["named"]; + json!({ "checked": true, "digest": digest, "auto": auto, "named": local.named, "same": digest == p["stable"]["digest"] && auto_same && named_same }) + }; + let s = &result["shadow"]; + let plan = &p["shadow"]; + // Which method a shadow runs, or why none can: planned again from the same + // job, memory and budget, by a verifier of the same engine. + let replanned = (plan.is_object() && same_engine).then(|| Contract::read(request).ok().flatten()).flatten().map(|c| { + let chosen = p["choice"].as_str().unwrap_or(""); + shadow_plan(reg, request, &Host::new(job_bytes), &c, provider_seconds(&p["routes"], chosen)) + }); + let as_planned = replanned.as_ref().is_none_or(|again| again["route"] == plan["route"] && (!again["route"].is_null() || again["code"] == plan["code"])); + let shadow = if s.get("ran").is_none() { + json!({ "checked": false, "why": "no provider answered this job, so it has no shadow" }) + } else if !as_planned { + let again = replanned.as_ref().map_or(Value::Null, |a| if a["route"].is_null() { a["code"].clone() } else { a["route"].clone() }); + json!({ "checked": true, "same": false, "why": format!("this engine plans {again} for this shadow, and the reasoning says otherwise") }) + } else if s["ran"] == true { + let req = &s["request"]; + let run = catalog::plan_plain(reg, req, job_bytes).and_then(|pl| reg.run(req, &pl))?; + json!({ "checked": true, "same": run["counts"] == s["counts"] && run["accuracy"]["class"] == s["accuracy"]["class"] }) + } else if s["code"] == "failed" && plan["route"].is_string() { + // The host says the shadow it planned failed: run it, and see. + let req = &plan["request"]; + match catalog::plan_plain(reg, req, job_bytes).and_then(|pl| reg.run(req, &pl)) { + Ok(_) => json!({ "checked": true, "same": false, "why": "the host says its shadow failed, and it runs here" }), + Err(e) => json!({ "checked": true, "same": true, "why": format!("it fails here too: {e}") }), + } + } else if replanned.is_some() { + json!({ "checked": true, "same": true, "why": "no shadow could be planned, and none can here" }) + } else { + // Sealed by another engine, whose version is its host's word: what this one + // plans is said, and the receipt is held neither way. + let here = plan.is_object().then(|| Contract::read(request).ok().flatten()).flatten().map(|c| { + let chosen = p["choice"].as_str().unwrap_or(""); + let a = shadow_plan(reg, request, &Host::new(job_bytes), &c, provider_seconds(&p["routes"], chosen)); + if a["route"].is_null() { a["code"].clone() } else { a["route"].clone() } + }); + json!({ "checked": false, "same": null, "why": format!("no shadow could be planned, the reasoning says, and it was sealed by another engine; this one plans {}, so the receipt is not held here either way", here.unwrap_or(Value::Null)) }) + }; + // Held only where everything that applies was checked here, by this engine: a + // receipt sealed by another engine version is held neither way. + // Another engine version prices and plans by its own rules: what differs is said, + // and the receipt is held neither way. + let holds = if !same_engine { + Value::Null + } else if priced["same"] == false || shadow["same"] == false { + json!(false) + } else if shadow.get("same") == Some(&Value::Null) { + Value::Null + } else { + json!(true) + }; + Ok(json!({ "holds": holds, "engine": { "sealed_by": engine, "this": super::schema::ENGINE_VERSION, "same": same_engine }, "priced": priced, "shadow": shadow })) +} + +#[cfg(test)] +mod tests; diff --git a/wai/wai-quantum/src/engine/planner/tests.rs b/wai/wai-quantum/src/engine/planner/tests.rs new file mode 100644 index 000000000..ba070fb9f --- /dev/null +++ b/wai/wai-quantum/src/engine/planner/tests.rs @@ -0,0 +1,1533 @@ +use super::*; +use crate::engine::{job, provider}; +use ed25519_dalek::SigningKey; + +const BELL: &str = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;\n"; +const ROT: &str = "OPENQASM 3.0;\nqubit[2] q;\nrx(0.3) q[0];\ncx q[0], q[1];\n"; +const GIB: u64 = 1 << 30; + +fn reg() -> &'static Registry { + Registry::builtins() +} + +fn wide(n: u32) -> String { + format!("OPENQASM 3.0;\nqubit[{n}] q;\nrx(0.3) q;\ncx q[0], q[1];\n") +} + +fn seal_local(req: &Value) -> Value { + job::run(req, GIB, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" })).unwrap() +} + +fn route<'a>(reasoning: &'a Value, name: &str) -> &'a Value { + reasoning["routes"].as_array().unwrap().iter().find(|r| r["route"] == name).unwrap_or_else(|| panic!("no route {name}: {reasoning}")) +} + +fn code<'a>(reasoning: &'a Value, name: &str) -> Option<&'a str> { + route(reasoning, name)["rejected"]["code"].as_str() +} + +fn considered(req: &Value, cap: u64) -> Considered { + consider(reg(), req, &Host::new(cap)).unwrap() +} + +/// The class table of section 8.7, every pair, written out here by hand. +#[test] +fn a_class_meets_what_the_table_says_and_nothing_else() { + let table: [(&str, &[&str]); 9] = [ + ("bit-exact", &["bit-exact"]), + ("exact", &["bit-exact", "exact"]), + ("single", &["bit-exact", "exact", "single"]), + ("bounded", &["bit-exact", "exact", "bounded"]), + ("estimate", &["bit-exact", "exact", "bounded", "estimate"]), + ("heuristic", &["bit-exact", "exact", "single", "bounded", "estimate", "heuristic"]), + ("measured", &["measured"]), + ("simulated", &["simulated"]), + ("any", &["bit-exact", "exact", "single", "bounded", "estimate", "heuristic", "measured", "simulated"]), + ]; + assert_eq!(table.iter().map(|t| t.0).collect::>(), CLASSES); + for (wanted, met) in table { + for got in ["bit-exact", "exact", "single", "bounded", "estimate", "heuristic", "measured", "simulated"] { + assert_eq!(meets(wanted, got), met.contains(&got), "{wanted} of {got}"); + } + } + // A device is in no classical class, and a class nobody knows meets only `any`. + assert!(!meets("heuristic", "measured") && !meets("exact", "later") && meets("any", "later")); +} + +/// An amount is compared as digits, with no double between them. +#[test] +fn amounts_are_compared_exactly() { + use std::cmp::Ordering::*; + for (a, b, want) in [("0.1", "0.10", Equal), ("0010", "10.0", Equal), ("0.3", "0.30000000000000000000000000000001", Less), ("10", "9.99", Greater), ("1", "1.0000000000000000000000000000000000001", Less), ("0", "0.0", Equal), ("100", "99", Greater)] { + assert_eq!(decimal_cmp(a, b), want, "{a} {b}"); + assert_eq!(decimal_cmp(b, a), want.reverse(), "{b} {a}"); + } + for ok in ["0", "0.50", "12", "007.5"] { + assert!(is_decimal(ok), "{ok}"); + } + for bad in ["", ".5", "5.", "1e3", "-1", "1,5", "0x10", " 1"] { + assert!(!is_decimal(bad), "{bad}"); + } +} + +/// A contract that does not read is refused, member by member: read as absent, +/// a misspelt requirement would drop in silence. +#[test] +fn a_contract_that_does_not_read_is_refused_with_its_code() { + for c in [ + json!(5), + json!([]), + json!({ "deadline": 30 }), + json!({ "exactness": "nearly" }), + json!({ "exactness": 3 }), + json!({ "max_cost": "0.50" }), + json!({ "max_cost": { "amount": "0.50" } }), + json!({ "max_cost": { "amount": 0.5, "currency": "USD" } }), + json!({ "max_cost": { "amount": "1e3", "currency": "USD" } }), + json!({ "max_cost": { "amount": "1", "currency": "" } }), + json!({ "max_cost": { "amount": "1", "currency": "USD", "more": 1 } }), + json!({ "deadline_seconds": 0 }), + json!({ "deadline_seconds": -1 }), + json!({ "deadline_seconds": "soon" }), + json!({ "max_joules": 0 }), + json!({ "providers": "sometimes" }), + json!({ "providers": true }), + ] { + let e = catalog::plan(&json!({ "qasm": BELL, "contract": c }), GIB).unwrap_err(); + assert_eq!(refusal::codes_in(&e).last().copied(), Some("J070"), "{c}: {e}"); + } + let host = Host::new(GIB).with_quotes(vec![Quote::new("lab", "lab:device", "silicon")]); + let e = consider(reg(), &json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "never" } }), &host).unwrap_err(); + assert_eq!(refusal::codes_in(&e), ["J070"], "{e}"); + // Null is what absent is, everywhere in a job. + assert!(!has_contract(&json!({ "qasm": BELL, "contract": null }))); + assert!(catalog::plan(&json!({ "qasm": BELL, "contract": { "exactness": null, "max_cost": null, "deadline_seconds": null, "max_joules": null, "providers": null } }), GIB).is_ok()); +} + +/// A result less what a contract adds to it. +fn answer_of(body: &Value) -> Value { + let mut r = body["result"].clone(); + let o = r.as_object_mut().unwrap(); + for k in ["planner", "receipt", "elapsed_ms"] { + o.shift_remove(k); + } + r +} + +/// Absent members keep today's behaviour: a contract that asks nothing, or only +/// what `auto`'s pick already meets, runs what `auto` picks, to the same bytes. +#[test] +fn a_contract_that_asks_nothing_changes_nothing_but_the_reasoning() { + for (qasm, extra) in [ + (BELL, json!({ "shots": 1000, "seed": 4 })), + (ROT, json!({ "shots": 300, "observables": ["Z0 Z1"], "amplitudes": ["00"] })), + ("OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nt q[0];\ncx q[0], q[1];\n", json!({ "shots": 50 })), + (BELL, json!({ "shots": 100, "noise": { "depolarizing_2q": 0.02 } })), + (&wide(40), json!({ "shots": 10 })), + ] { + let mut plain = json!({ "qasm": qasm }); + plain.as_object_mut().unwrap().extend(extra.as_object().unwrap().clone()); + let (auto, _) = job::plan_and_run(&plain, GIB).unwrap(); + for contract in [json!({}), json!({ "providers": "never" }), json!({ "deadline_seconds": 1e9 }), json!({ "providers": "allowed" })] { + let mut under = plain.clone(); + under["contract"] = contract.clone(); + let (p, _) = job::plan_and_run(&under, GIB).unwrap(); + assert_eq!(p.method, auto.method, "{under}"); + assert_eq!(p.memory_bytes, auto.memory_bytes, "{under}"); + let (a, b) = (seal_local(&plain), seal_local(&under)); + assert_eq!(answer_of(&a), answer_of(&b), "{under}"); + assert_eq!(b["result"]["planner"]["auto"], format!("method:{}", auto.method), "{under}"); + assert_eq!(b["result"]["planner"]["choice"], format!("method:{}", auto.method), "{under}"); + assert!(job::check(&b).valid(), "{:?}\n{under}", job::check(&b).reasons); + } + // And with no contract at all, nothing of a planner. + assert!(seal_local(&plain)["result"].get("planner").is_none()); + } + // A method whose time is not known keeps its place, until a deadline asks. + let pauli = json!({ "qasm": wide(100), "observables": ["Z0 Z1"], "contract": {} }); + assert_eq!(catalog::plan(&pauli, GIB).unwrap().method, "pauli"); +} + +/// With a class named, the cheapest route of that class runs: less money, then +/// less time to the millisecond, then less memory. +#[test] +fn the_cheapest_route_that_meets_the_contract_runs() { + let t = "OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\nt q[0];\ncx q[0], q[1];\nc = measure q;\n"; + for (qasm, wanted, method) in [ + (BELL, "exact", "stabilizer"), + (BELL, "bit-exact", "exact"), + (t, "exact", "exact"), + (ROT, "exact", "statevector"), + (ROT, "heuristic", "statevector"), + ] { + let req = json!({ "qasm": qasm, "shots": 100, "contract": { "exactness": wanted } }); + let body = seal_local(&req); + assert_eq!(body["result"]["method"], method, "{qasm} {wanted}: {}", body["result"]["planner"]); + assert_eq!(body["result"]["planner"]["choice"], format!("method:{method}")); + assert_eq!(route(&body["result"]["planner"], &format!("method:{method}"))["outcome"], "chosen"); + let c = job::check(&body); + assert!(c.valid(), "{:?}", c.reasons); + assert_eq!(c.planner.as_ref().unwrap()["choice"], format!("method:{method}")); + } + // A time that matters decides: 26 qubits' double-precision state is quicker + // at the planner's rates than the fixed-point one. + let many = "OPENQASM 3.0;\nqubit[26] q;\nbit[26] c;\nh q;\nt q;\ncx q[0], q[1];\nt q[0];\nc = measure q;\n"; + let p = catalog::plan(&json!({ "qasm": many, "shots": 1, "contract": { "exactness": "exact" } }), 8 * GIB).unwrap(); + assert_eq!(p.method, "statevector", "{}", p.why); + assert!(p.why.contains("the cheapest of"), "{}", p.why); +} + +/// The other half of a choice: what each route was rejected for, and its price +/// wherever it has one. +#[test] +fn every_route_it_sees_is_listed_with_its_price_or_why_not() { + let req = json!({ "qasm": ROT, "shots": 100, "contract": { "exactness": "exact" } }); + let c = considered(&req, GIB); + let p = &c.reasoning; + let names: Vec<&str> = p["routes"].as_array().unwrap().iter().map(|r| r["route"].as_str().unwrap()).collect(); + for m in reg().methods() { + assert!(names.contains(&format!("method:{}", m.name()).as_str()), "{}", m.name()); + } + assert_eq!(p["wanted"], "exact"); + assert_eq!(p["wanted_from"], "contract"); + assert_eq!(p["host"]["job_bytes"], GIB); + let sv = route(p, "method:statevector"); + assert_eq!((sv["outcome"].as_str(), sv["class"].as_str(), sv["host_dependent"].as_bool()), (Some("chosen"), Some("exact"), Some(false))); + assert_eq!(sv["price"]["money"], json!({ "free": true })); + assert_eq!(sv["price"]["time"]["basis"], "nominal"); + assert_eq!(sv["price"]["time"]["seconds"].as_f64(), Some((2u64 << 2) as f64 / 1e9)); + assert_eq!(sv["price"]["memory_bytes"].as_u64(), Some(catalog::statevector_bytes(2) + 100 * 24)); + // Not dyadic: the bit-exact method cannot, and says why; a heuristic's price + // is shown beside its rejection. + assert_eq!(code(p, "method:exact"), Some("cannot")); + assert!(route(p, "method:exact")["rejected"]["why"].as_str().unwrap().contains("dyadic"), "{p}"); + let mps = route(p, "method:mps"); + assert_eq!((mps["rejected"]["code"].as_str(), mps["class"].as_str()), (Some("class"), Some("heuristic"))); + assert!(mps["price"]["memory_bytes"].is_number()); + assert!(mps["rejected"]["why"].as_str().unwrap().contains("before it runs"), "{mps}"); + assert_eq!(code(p, "method:statevector_single"), Some("class"), "{p}"); + assert_eq!(route(p, "method:statevector_single")["host_dependent"], true); + // A method that cannot take it, whatever its class: no price, and why. + assert_eq!(code(p, "method:tensor_network"), Some("cannot")); + assert!(route(p, "method:tensor_network")["price"].is_null()); + // A class that is not wanted is said first, the same on every host. + assert_eq!(code(p, "method:pauli"), Some("class")); +} + +/// From exact to approximate, nothing falls back: the job names exact, or names +/// no class and so keeps auto's; only asking for less lets less run. +#[test] +fn nothing_falls_back_from_exact_to_approximate() { + let w = wide(40); + // Past every exact route: the matrix product state can, and is not asked. + let req = json!({ "qasm": w, "shots": 10, "contract": { "exactness": "exact" } }); + let e = catalog::plan(&req, GIB).unwrap_err(); + assert_eq!(refusal::codes_in(&e).last().copied(), Some("J071"), "{e}"); + assert!(e.contains("method:mps") && e.contains("method:statevector") && e.contains("heuristic"), "{e}"); + let c = considered(&req, GIB); + assert_eq!((c.reasoning["choice"].as_str(), c.plan.is_none()), (None, true)); + assert_eq!(c.reasoning["refusal"]["code"], "J071"); + // Asked for, and labelled: it says heuristic, and its result what it was. + let asked = json!({ "qasm": w, "shots": 10, "contract": { "exactness": "heuristic" } }); + let p = catalog::plan(&asked, GIB).unwrap(); + assert_eq!(p.method, "mps"); + // No class named, and a deadline auto's pick misses: only as exact may take over. + let dense = wide(30); + let plain = catalog::plan(&json!({ "qasm": dense, "shots": 10 }), 72 * GIB).unwrap(); + assert_eq!(plain.method, "statevector"); + let tight = json!({ "qasm": dense, "shots": 10, "contract": { "deadline_seconds": 1 } }); + let e = catalog::plan(&tight, 72 * GIB).unwrap_err(); + assert!(refusal::codes_in(&e).contains(&"J071"), "{e}"); + let c = considered(&tight, 72 * GIB); + assert_eq!((c.reasoning["wanted"].as_str(), c.reasoning["wanted_from"].as_str(), c.reasoning["auto"].as_str()), (Some("exact"), Some("auto"), Some("method:statevector"))); + assert_eq!(code(&c.reasoning, "method:statevector"), Some("deadline")); + assert_eq!(code(&c.reasoning, "method:mps"), Some("class"), "the quicker route is the less exact one, and it is not taken"); + // With that class given up by name, the same deadline is met. + let given_up = json!({ "qasm": dense, "shots": 10, "contract": { "deadline_seconds": 1, "exactness": "heuristic" } }); + assert_eq!(catalog::plan(&given_up, 72 * GIB).unwrap().method, "mps"); +} + +/// A class named by the job's own method holds too: naming a method names the +/// route, and it is held to the rest of the contract. +#[test] +fn a_named_method_is_held_to_the_contract_and_nothing_stands_in_for_it() { + let named = json!({ "qasm": ROT, "shots": 10, "method": "statevector", "contract": { "exactness": "exact" } }); + let body = seal_local(&named); + assert_eq!(body["result"]["method"], "statevector"); + let p = &body["result"]["planner"]; + assert_eq!(code(p, "method:mps"), Some("not_named")); + assert!(route(p, "method:mps")["price"].is_null(), "only what the job names is priced: {p}"); + assert_eq!(p["auto"], Value::Null); + assert!(job::check(&body).valid(), "{:?}", job::check(&body).reasons); + // Its class is what it is, and a higher one wanted refuses it. + let e = catalog::plan(&json!({ "qasm": ROT, "shots": 10, "method": "mps", "contract": { "exactness": "exact" } }), GIB).unwrap_err(); + assert!(e.ends_with("[J071]"), "{e}"); + // A method that cannot take the job, or that does not exist. + let e = catalog::plan(&json!({ "qasm": ROT, "shots": 10, "method": "stabilizer", "contract": {} }), GIB).unwrap_err(); + assert!(e.contains("Clifford") && e.ends_with("[J071]"), "{e}"); + let e = catalog::plan(&json!({ "qasm": ROT, "shots": 10, "method": "nonsense", "contract": {} }), GIB).unwrap_err(); + assert!(e.ends_with("[J010]"), "{e}"); + // Named with no class, its own stands: a heuristic may run as itself. + let body = seal_local(&json!({ "qasm": ROT, "shots": 10, "method": "mps", "contract": {} })); + assert_eq!(body["result"]["planner"]["wanted_from"], "named"); + assert!(job::check(&body).valid(), "{:?}", job::check(&body).reasons); +} + +/// A time nobody can state does not meet a deadline; a time that can does. +#[test] +fn an_unknown_time_does_not_meet_a_deadline() { + let w = wide(100); + let req = json!({ "qasm": w, "observables": ["Z0 Z1"], "contract": { "exactness": "bounded" } }); + let p = catalog::plan(&req, 8 * GIB).unwrap(); + assert_eq!(p.method, "pauli", "{}", p.why); + let c = considered(&json!({ "qasm": w, "observables": ["Z0 Z1"], "contract": { "exactness": "bounded", "deadline_seconds": 3600 } }), 8 * GIB); + let r = route(&c.reasoning, "method:pauli"); + assert_eq!(r["rejected"]["code"], "deadline_unknown", "{r}"); + assert!(r["price"]["time"]["seconds"].is_null()); + assert!(r["rejected"]["why"].as_str().unwrap().contains("does not predict"), "{r}"); + assert!(c.refusal.unwrap().ends_with("[J071]")); +} + +/// A ceiling is held by a live reading, so a route nothing reads is refused, whatever +/// its estimate; an estimate past the ceiling refuses a job clearly over it, and one +/// under it promises nothing. A run stopped at it says so, in a receipt both forms +/// of which a verifier holds. +#[test] +fn an_energy_ceiling_is_held_by_a_live_reading_and_a_stopped_run_says_so() { + use crate::engine::energy::Held as Figure; + let req = json!({ "qasm": BELL, "shots": 100, "contract": { "max_joules": 2.0 } }); + let c = considered(&req, GIB); + assert_eq!(code(&c.reasoning, "method:stabilizer"), Some("energy_unwatched")); + assert!(c.refusal.unwrap().contains("reads no run while it runs")); + let figure = |estimate: Option, watched: bool| Figure { estimate: estimate.map_or(Err("no estimate yet".to_string()), |j| Ok((j, "a test's estimate".to_string()))), watch: if watched { Ok("a test's reading".to_string()) } else { Err("nothing reads it".to_string()) } }; + let by_method = |p: &Plan| -> Figure { + match p.method.as_str() { + "stabilizer" => figure(Some(5.0), true), + "exact" => figure(Some(1.5), true), + "cutrank" => figure(None, true), + "statevector" => figure(Some(0.1), false), + _ => figure(None, false), + } + }; + let host = Host::new(GIB).with_joules(&by_method); + let job = json!({ "qasm": BELL, "shots": 100, "contract": { "exactness": "exact", "max_joules": 2.0 } }); + let c = consider(reg(), &job, &host).unwrap(); + assert_eq!(c.reasoning["choice"], "method:exact", "{}", c.reasoning); + assert_eq!(code(&c.reasoning, "method:stabilizer"), Some("energy"), "an estimate clearly past it refuses"); + assert_eq!(route(&c.reasoning, "method:exact")["price"]["energy"], json!({ "joules": 1.5, "basis": "a test's estimate", "watch": "a test's reading" })); + assert_eq!(code(&c.reasoning, "method:cutrank"), None, "no estimate is no refusal: the reading holds the ceiling"); + assert_eq!(code(&c.reasoning, "method:statevector"), Some("energy_unwatched"), "an estimate under it promises nothing"); + assert!(route(&c.reasoning, "method:statevector")["rejected"]["why"].as_str().unwrap().contains("nothing reads it"), "{}", c.reasoning); + assert_eq!(c.reasoning["stable"]["choice"], false, "the host's reading decided"); + let good = job::run_with(&job, GIB, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" }), Some(&by_method)).unwrap(); + assert_eq!(reasons(&good), Vec::<&str>::new()); + cases(&good, vec![ + // A route no reading can stop, said to meet the ceiling, and its form. + (&[PLANNER_ROUTE, PLANNER_CHOICE], Box::new(|b| { at(b, "method:exact")["price"]["energy"].as_object_mut().unwrap().shift_remove("watch"); })), + (&[PLANNER_ROUTE], Box::new(|b| { + let e = &mut at(b, "method:statevector")["price"]["energy"]; + e.as_object_mut().unwrap().shift_remove("unwatched"); + e["watch"] = json!("a reading"); + })), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:exact")["price"]["energy"]["watch"] = json!(true))), + // Read and not read: a route says one or the other. + (&[PLANNER_FORM], Box::new(|b| at(b, "method:statevector")["price"]["energy"]["watch"] = json!("a reading"))), + ]); + // Stopped at it. + let d = decide(reg(), &job, &host).unwrap(); + let Choice::Local(plan) = &d.choice else { panic!() }; + let mut r = stopped_result(reg(), &job, plan, &d.reasoning, &Stopped { joules: 2.25, elapsed_ms: 7, read: "a test's reading".into() }); + complete(&mut r, &d.reasoning).unwrap(); + let stopped = job::seal(&job, plan, r, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" })); + assert_eq!(reasons(&stopped), Vec::<&str>::new(), "{}", stopped["result"]); + assert_eq!(stopped["result"]["planner"]["kept"]["energy"], json!({ "max_joules": 2.0, "joules": 2.25, "kept": false })); + assert!(missed(&stopped["result"])); + // A reading exactly at the ceiling stops a run, and a stopped run kept nothing. + let mut at = stopped_result(reg(), &job, plan, &d.reasoning, &Stopped { joules: 2.0, elapsed_ms: 7, read: "a test's reading".into() }); + assert_eq!(at["planner"]["kept"]["energy"], json!({ "max_joules": 2.0, "joules": 2.0, "kept": false })); + complete(&mut at, &d.reasoning).unwrap(); + assert_eq!(reasons(&job::seal(&job, plan, at, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" }))), Vec::<&str>::new()); + // Nothing here reads a provider's run, so none is stopped by a reading here. + assert!(reasons(&resealed(&stopped, |b| b["result"]["method"] = json!("provider"))).contains(&STOPPED)); + cases(&stopped, vec![ + (&[STOPPED], Box::new(|b| b["result"]["stopped"]["at"] = json!("deadline"))), + (&[STOPPED], Box::new(|b| b["result"]["stopped"]["max_joules"] = json!(9))), + (&[STOPPED], Box::new(|b| b["result"]["stopped"]["note"] = json!("x"))), + // Under its ceiling, with what it kept to match. + (&[STOPPED], Box::new(|b| { b["result"]["stopped"]["joules"] = json!(1.0); b["result"]["planner"]["kept"]["energy"]["joules"] = json!(1.0); })), + // An answer it says it did not give. + (&[STOPPED], Box::new(|b| b["result"]["counts"] = json!({ "00": 100 }))), + (&[STOPPED], Box::new(|b| b["result"]["accuracy"]["class"] = json!("exact"))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["energy"]["kept"] = json!(true))), + ]); + // On a job with no ceiling, stopped is no such thing. + let plain = seal_local(&json!({ "qasm": BELL, "shots": 100 })); + assert_eq!(reasons(&resealed(&plain, |b| b["result"]["stopped"] = json!({ "at": "max_joules" }))), vec![STOPPED]); +} + +/// A quote as a host brings it. +fn quote(name: &str, provenance: &str, money: Value, seconds: Option) -> Quote { + let mut q = Quote::new(name, format!("{name}:device"), provenance); + q.money = money; + q.seconds = seconds; + q.leaves_out = vec!["energy".into(), "mitigation".into(), "decoder".into(), "charged".into()]; + q.program = json!({ "shots": 1000, "native_gates": 9, "two_qubit_gates": 1, "swaps": 0 }); + q +} + +fn usd(a: &str) -> Value { + json!({ "free": false, "amount": a, "currency": "USD", "unit": "shot" }) +} + +fn decided(req: &Value, quotes: Vec) -> Considered { + consider(reg(), req, &Host::new(GIB).with_quotes(quotes)).unwrap() +} + +/// From a simulator to a device and the reverse, nothing falls back: a device +/// is reached by asking for its class, or by naming the provider. +#[test] +fn nothing_falls_back_between_a_simulator_and_a_device() { + let quotes = || vec![quote("sim", "simulator:a state vector", json!({ "free": true }), Some(0.0)), quote("qpu", "silicon", usd("0.30"), Some(12.0))]; + let ask = |c: Value| json!({ "qasm": BELL, "shots": 1000, "contract": c }); + // Allowed, and no class: what auto picks here, and no device. + let c = decided(&ask(json!({ "providers": "allowed" })), quotes()); + assert_eq!(c.reasoning["choice"], "method:stabilizer", "{}", c.reasoning); + assert_eq!(code(&c.reasoning, "provider:qpu"), Some("class")); + assert_eq!(code(&c.reasoning, "provider:sim"), Some("class")); + // Wanting exact, no provider's counts are it, free or not. + let c = decided(&ask(json!({ "exactness": "exact", "providers": "allowed" })), quotes()); + assert_eq!(c.reasoning["choice"], "method:stabilizer"); + assert!(route(&c.reasoning, "provider:sim")["rejected"]["why"].as_str().unwrap().contains("simulated"), "{}", c.reasoning); + // Wanting a device: no local method, and no simulator however free. + let c = decided(&ask(json!({ "exactness": "measured", "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } })), quotes()); + assert_eq!(c.reasoning["choice"], "provider:qpu", "{}", c.reasoning); + assert_eq!(code(&c.reasoning, "provider:sim"), Some("class")); + assert_eq!(code(&c.reasoning, "method:stabilizer"), Some("class")); + // Wanting a simulator's counts: no device. + let c = decided(&ask(json!({ "exactness": "simulated", "providers": "allowed" })), quotes()); + assert_eq!(c.reasoning["choice"], "provider:sim"); + assert_eq!(code(&c.reasoning, "provider:qpu"), Some("class")); + // The device is down: it does not become the simulator, or the reverse. + let e = decided(&ask(json!({ "exactness": "measured", "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } })), vec![quote("sim", "simulator", json!({ "free": true }), Some(0.0))]); + assert!(e.refusal.unwrap().ends_with("[J071]")); + let e = decided(&ask(json!({ "exactness": "simulated", "providers": "allowed" })), vec![quote("qpu", "silicon", json!({ "free": true }), Some(0.0))]); + assert!(e.refusal.unwrap().ends_with("[J071]")); + // Asking for a device with providers not allowed is refused, and says so. + let e = decided(&ask(json!({ "exactness": "measured" })), quotes()); + assert_eq!(code(&e.reasoning, "provider:qpu"), Some("providers")); + assert!(e.refusal.unwrap().contains("does not allow a provider")); + // An approximate simulator is not what simulated asks. + let mut approx = quote("sim", "simulator:a truncated network", json!({ "free": true }), Some(0.0)); + approx.approximate = true; + let e = decided(&ask(json!({ "exactness": "simulated", "providers": "allowed" })), vec![approx.clone()]); + assert!(e.reasoning["routes"].as_array().unwrap().iter().any(|r| r["route"] == "provider:sim" && r["rejected"]["why"].as_str().unwrap().contains("approximate")), "{}", e.reasoning); + let c = decided(&ask(json!({ "exactness": "any", "providers": "allowed" })), vec![approx.clone()]); + // A provider that says no time is not quicker than a local route that takes + // less than half a millisecond: each to the nearest millisecond, a tie, and + // the local route first. + assert_eq!(c.reasoning["choice"], "method:stabilizer", "{}", c.reasoning); + // A tie to the millisecond goes to the local route. + approx.seconds = Some(0.0005); + let c = decided(&ask(json!({ "exactness": "any", "providers": "allowed" })), vec![approx]); + assert_eq!(c.reasoning["choice"], "method:stabilizer", "{}", c.reasoning); +} + +/// What a provider costs, against the ceiling: money only under a stated ceiling +/// in its own currency, and an unknown is never read as free. +#[test] +fn a_provider_is_held_to_the_cost_ceiling_and_an_unknown_is_not_free() { + let ask = |ceiling: Option<(&str, &str)>| { + let mut c = json!({ "exactness": "measured", "providers": "allowed" }); + if let Some((a, cur)) = ceiling { + c["max_cost"] = json!({ "amount": a, "currency": cur }); + } + json!({ "qasm": BELL, "shots": 1000, "contract": c }) + }; + let priced = |a: &str| vec![quote("qpu", "silicon", usd(a), Some(12.0))]; + let of = |c: &Considered| code(&c.reasoning, "provider:qpu").map(str::to_string); + assert_eq!(of(&decided(&ask(None), priced("0.3"))).as_deref(), Some("cost_no_ceiling"), "nothing bounds what would be spent"); + assert_eq!(of(&decided(&ask(Some(("0.29", "USD"))), priced("0.3"))).as_deref(), Some("cost")); + assert_eq!(of(&decided(&ask(Some(("0.3", "USD"))), priced("0.30"))), None, "at the ceiling meets it"); + assert_eq!(of(&decided(&ask(Some(("100", "EUR"))), priced("0.3"))).as_deref(), Some("cost_currency"), "nothing is converted"); + let unknown = vec![quote("qpu", "silicon", json!({ "free": false, "unknown": "the provider gives no estimate" }), Some(12.0))]; + assert_eq!(of(&decided(&ask(Some(("100", "USD"))), unknown.clone())).as_deref(), Some("cost_unknown")); + assert_eq!(of(&decided(&ask(None), unknown)).as_deref(), Some("cost_no_ceiling")); + assert_eq!(of(&decided(&ask(Some(("100", "USD"))), vec![quote("qpu", "silicon", usd("lots"), Some(1.0))])).as_deref(), Some("cost_unknown"), "an amount that is no decimal is unknown"); + // The least it can come to is not what it will: under a ceiling it is not + // known to meet, and above it, it is known not to. + let least = |a: &str| vec![quote("qpu", "silicon", json!({ "free": false, "amount": a, "currency": "USD", "unit": "minute", "at_least": true }), Some(12.0))]; + assert_eq!(of(&decided(&ask(Some(("100", "USD"))), least("0.3"))).as_deref(), Some("cost_at_least")); + assert!(route(&decided(&ask(Some(("100", "USD"))), least("0.3")).reasoning, "provider:qpu")["rejected"]["why"].as_str().unwrap().contains("at least 0.3 USD")); + assert_eq!(of(&decided(&ask(Some(("0.29", "USD"))), least("0.3"))).as_deref(), Some("cost")); + assert_eq!(of(&decided(&ask(Some(("0.3", "USD"))), least("0.3"))).as_deref(), Some("cost_at_least"), "at the ceiling, and it may come to more"); + let named_least = decided(&json!({ "qasm": BELL, "shots": 1000, "provider": "qpu", "contract": { "providers": "allowed" } }), least("0.3")); + assert_eq!(named_least.reasoning["choice"], "provider:qpu", "named with no ceiling, its cost is the person's to confirm"); + // Free needs no ceiling. + assert_eq!(of(&decided(&ask(None), vec![quote("qpu", "silicon", json!({ "free": true }), Some(1.0))])), None); + // Named by the job, its cost is the person's to confirm, as it is with no contract. + let named = json!({ "qasm": BELL, "shots": 1000, "provider": "qpu", "contract": { "providers": "allowed" } }); + let c = decided(&named, priced("0.3")); + assert_eq!(c.reasoning["choice"], "provider:qpu"); + assert_eq!(c.reasoning["wanted_from"], "named"); + assert_eq!(c.reasoning["wanted"], "measured"); + assert_eq!(code(&c.reasoning, "method:stabilizer"), Some("not_named")); + // Named, a ceiling still holds, and a named device is still held to its class. + let e = decided(&json!({ "qasm": BELL, "provider": "qpu", "contract": { "providers": "allowed", "max_cost": { "amount": "0.1", "currency": "USD" } } }), priced("0.3")); + assert_eq!(code(&e.reasoning, "provider:qpu"), Some("cost")); + let e = decided(&json!({ "qasm": BELL, "provider": "qpu", "contract": { "providers": "allowed", "exactness": "simulated" } }), priced("0.3")); + assert_eq!(code(&e.reasoning, "provider:qpu"), Some("class")); + // A provider this host has not brought is refused as today. + let e = consider(reg(), &json!({ "qasm": BELL, "provider": "other", "contract": { "providers": "allowed" } }), &Host::new(GIB)).unwrap_err(); + assert!(e.ends_with("[J002]"), "{e}"); +} + +/// What it costs decides among providers: money, then time, then its name; and +/// a time it does not state does not meet a deadline. +#[test] +fn the_cheapest_provider_is_chosen_and_what_its_estimate_leaves_out_is_said() { + let req = |c: Value| json!({ "qasm": BELL, "shots": 1000, "contract": c }); + let base = json!({ "exactness": "measured", "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } }); + let c = decided(&req(base.clone()), vec![quote("dear", "silicon", usd("0.9"), Some(1.0)), quote("cheap", "silicon", usd("0.2"), Some(100.0)), quote("free", "silicon", json!({ "free": true }), None)]); + assert_eq!(c.reasoning["choice"], "provider:free", "{}", c.reasoning); + let c = decided(&req(base.clone()), vec![quote("slow", "silicon", usd("0.2"), Some(100.0)), quote("quick", "silicon", usd("0.20"), Some(10.0))]); + assert_eq!(c.reasoning["choice"], "provider:quick"); + let mut with_deadline = base.clone(); + with_deadline["deadline_seconds"] = json!(30); + let c = decided(&req(with_deadline), vec![quote("quiet", "silicon", usd("0.1"), None), quote("slow", "silicon", usd("0.1"), Some(100.0)), quote("quick", "silicon", usd("0.5"), Some(10.0))]); + assert_eq!(c.reasoning["choice"], "provider:quick"); + assert_eq!(code(&c.reasoning, "provider:quiet"), Some("deadline_unknown")); + assert_eq!(code(&c.reasoning, "provider:slow"), Some("deadline")); + // What the price is and what it leaves out, on the route. + let r = route(&c.reasoning, "provider:quick"); + assert_eq!(r["price"]["money"]["amount"], "0.5"); + assert_eq!(r["price"]["leaves_out"], json!(["energy", "mitigation", "decoder", "charged"])); + assert_eq!(r["price"]["program"]["two_qubit_gates"], 1); + assert_eq!(r["provenance"], "silicon"); + assert_eq!(r["host_dependent"], true); + // No reading here can stop a provider's run. + let mut joules = base; + joules["max_joules"] = json!(1e9); + let c = decided(&req(joules), vec![quote("qpu", "silicon", usd("0.1"), Some(1.0))]); + assert_eq!(code(&c.reasoning, "provider:qpu"), Some("energy_unwatched")); + // One that cannot run the job says why, and nothing else of it is known. + let c = decided(&req(json!({ "exactness": "any", "providers": "allowed" })), vec![Quote::cannot("small", "this device holds 1 qubit")]); + let r = route(&c.reasoning, "provider:small"); + assert_eq!((r["rejected"]["code"].as_str(), r["rejected"]["why"].as_str(), r["price"].is_null()), (Some("cannot"), Some("this device holds 1 qubit"), true)); +} + +/// On a host that reaches no provider, a contract that allows one is met by what +/// is here or refused: the job service's case. +#[test] +fn a_host_that_reaches_no_provider_lists_none_and_never_stands_in() { + let c = considered(&json!({ "qasm": BELL, "shots": 10, "contract": { "providers": "allowed" } }), GIB); + assert_eq!(c.reasoning["host"]["providers"], json!([])); + assert!(c.reasoning["routes"].as_array().unwrap().iter().all(|r| r["kind"] == "local")); + assert_eq!(c.reasoning["choice"], "method:stabilizer"); + let e = considered(&json!({ "qasm": BELL, "shots": 10, "contract": { "providers": "allowed", "exactness": "measured" } }), GIB); + assert!(e.refusal.unwrap().ends_with("[J071]")); + let e = catalog::plan(&json!({ "qasm": BELL, "provider": "lab", "contract": { "providers": "allowed" } }), GIB).unwrap_err(); + assert!(e.ends_with("[J002]"), "{e}"); +} + +/// Beyond what the reader and the method refuse, the program's own limits: a +/// memory ceiling in the job's bytes is the host's, and a route past it is out. +#[test] +fn a_route_past_a_job_s_memory_is_rejected_for_it() { + // The fixed-point state of 26 qubits takes more than 1 GiB; today's plan says + // so and the host refuses at admission. Under a contract, the planner does. + let t26 = "OPENQASM 3.0;\nqubit[26] q;\nh q;\nt q;\n"; + let c = considered(&json!({ "qasm": t26, "shots": 1, "contract": { "exactness": "bit-exact" } }), GIB); + assert_eq!(code(&c.reasoning, "method:exact"), Some("memory")); + assert!(c.refusal.is_some()); +} + +/// What a plan is: a plan's form, or a refusal with the reasoning. +#[test] +fn a_contract_s_plan_states_its_reasoning_in_its_schema() { + let r = crate::engine::schema::Registry::engine(); + let bad = |errs: Vec, what: &str| assert!(errs.is_empty(), "{what}: {errs:#?}"); + let req = json!({ "qasm": BELL, "shots": 100, "contract": { "exactness": "exact", "deadline_seconds": 30, "max_cost": { "amount": "0.50", "currency": "USD" }, "providers": "allowed" } }); + bad(r.check("job-request.v1.json", &req), "the request"); + let v = plan_value(reg(), &req, GIB).unwrap(); + bad(r.check("plan.v1.json", &v), "the plan"); + assert_eq!(v["method"], "stabilizer"); + assert_eq!(v["planner"]["choice"], "method:stabilizer"); + let body = seal_local(&req); + bad(r.check("job.v1.json", &body), "the job"); + bad(r.check("job-result.v1.json", &body["result"]), "the result"); + assert_eq!(body["result"]["planner"]["kept"]["cost"]["kept"], true, "{}", body["result"]["planner"]["kept"]); + assert_eq!(body["result"]["planner"]["kept"]["deadline"]["kept"], true); + assert_eq!(body["result"]["planner"]["kept"]["deadline"]["seconds"].as_f64(), Some(30.0)); + // Every word a price can leave out is one its schema takes. + bad(r.check_value(&json!({ "$ref": "job-result.v1.json#/$defs/route_price/properties/leaves_out" }), &json!(LEFT_OUT)), "what a price leaves out"); + // A refusal, with every route's reason. + let refused = considered(&json!({ "qasm": ROT, "shots": 10, "contract": { "exactness": "bit-exact" } }), GIB); + bad(r.check_value(&json!({ "$ref": "job-result.v1.json#/$defs/planner" }), &refused.reasoning), "the refused reasoning"); + assert!(plan_value(reg(), &json!({ "qasm": ROT, "shots": 10, "contract": { "exactness": "bit-exact" } }), GIB).unwrap_err().ends_with("[J071]")); +} + +/// A contract is one job's: a set's items would lose its reasoning, so a set +/// refuses it, whether it is the set's or an item's. +#[test] +fn a_set_refuses_a_contract_rather_than_dropping_it() { + for req in [ + json!({ "programs": [BELL, BELL], "shots": 10, "contract": {} }), + json!({ "programs": [{ "qasm": BELL, "contract": { "exactness": "exact" } }, BELL], "shots": 10 }), + json!({ "qasm": "OPENQASM 3.0;\ninput float t;\nqubit q;\nrx(t) q;\n", "sweep": { "t": [0.1, 0.2] }, "shots": 10, "contract": {} }), + ] { + let e = crate::engine::sets::expand(&req).unwrap_err(); + assert!(e.ends_with("[J073]"), "{e}"); + } + assert!(crate::engine::sets::expand(&json!({ "programs": [BELL, BELL], "shots": 10 })).is_ok()); +} + +/// A result below the contract's class gives no answer, whatever plan it came +/// from: the mps method's truncation shows only once it has run. +#[test] +fn a_result_below_the_class_wanted_gives_no_answer() { + let dense = "OPENQASM 3.0;\nqubit[6] q;\nrx(0.3) q;\ncx q[0], q[1];\ncx q[1], q[2];\ncx q[2], q[3];\nrx(0.2) q;\ncx q[0], q[1];\ncx q[1], q[2];\ncx q[2], q[3];\n"; + let plain = json!({ "qasm": dense, "shots": 10, "method": "mps", "options": { "max_bond": 1 } }); + let p = catalog::plan(&plain, GIB).unwrap(); + let mut asked = plain.clone(); + asked["contract"] = json!({ "exactness": "exact" }); + // A plan that is not the planner's: its own plan refuses this job. + assert!(catalog::plan(&asked, GIB).is_err()); + let e = crate::engine::run::run(&asked, &p).unwrap_err(); + assert!(e.ends_with("[J072]"), "{e}"); + assert!(e.contains("heuristic") && e.contains("exact"), "{e}"); + // The same plan with less wanted runs. + asked["contract"] = json!({ "exactness": "heuristic" }); + assert!(crate::engine::run::run(&asked, &p).is_ok()); +} + +/// A host that ran a contract job and dropped the reasoning seals a result no +/// verifier passes. +#[test] +fn a_contract_job_sealed_without_its_reasoning_does_not_verify() { + let req = json!({ "qasm": BELL, "shots": 10, "contract": { "exactness": "exact" } }); + let p = catalog::plan(&req, GIB).unwrap(); + let result = crate::engine::run::run(&req, &p).unwrap(); + assert!(result.get("planner").is_none()); + let body = job::seal(&req, &p, result, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" })); + assert_eq!(job::check(&body).reasons, vec![PLANNER_FORM]); +} + +fn resealed(body: &Value, edit: impl Fn(&mut Value)) -> Value { + let mut both = json!({ "request": body["request"], "result": body["result"] }); + both["result"].as_object_mut().unwrap().shift_remove("receipt"); + edit(&mut both); + let mut res = both["result"].take(); + let req = both["request"].take(); + res["receipt"] = receipt::seal(&SigningKey::from_bytes(&[9; 32]), &req, &res); + json!({ "status": "done", "request": req, "result": res }) +} + +fn reasons(body: &Value) -> Vec<&'static str> { + let mut r = job::check(body).reasons; + r.sort_unstable(); + r +} + +fn routes_of(b: &mut Value) -> &mut Vec { + b["result"]["planner"]["routes"].as_array_mut().unwrap() +} + +fn at<'a>(b: &'a mut Value, name: &str) -> &'a mut Value { + routes_of(b).iter_mut().find(|r| r["route"] == name).unwrap() +} + +/// Each rule of section 8.7 on a local job, broken once and found alone, the +/// receipt sealed again so that nothing else is wrong with it. +#[test] +fn every_rule_a_verifier_holds_a_local_contract_job_to_is_broken_once_and_found_alone() { + let good = seal_local(&json!({ "qasm": ROT, "shots": 100, "contract": { "exactness": "exact", "deadline_seconds": 30, "max_cost": { "amount": "1", "currency": "USD" } } })); + assert_eq!(reasons(&good), Vec::<&str>::new(), "{}", good["result"]["planner"]); + type Edit = Box; + let cases: Vec<(&[&str], Edit)> = vec![ + (&[CONTRACT_FORM], Box::new(|b| b["request"]["contract"]["exactness"] = json!("nearly"))), + (&[CONTRACT_FORM], Box::new(|b| b["request"]["contract"]["deadline"] = json!(1))), + (&[PLANNER_FORM], Box::new(|b| { b["result"].as_object_mut().unwrap().shift_remove("planner"); })), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["format"] = json!("wai.quantum.planner/2"))), + (&[PLANNER_FORM], Box::new(|b| { b["result"]["planner"].as_object_mut().unwrap().shift_remove("kept"); })), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["choice"] = json!("method:another"))), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["auto"] = json!("method:another"))), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["wanted"] = json!("heuristic"))), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["wanted_from"] = json!("auto"))), + (&[PLANNER_FORM], Box::new(|b| { let r = routes_of(b)[0].clone(); routes_of(b).push(r); })), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:mps")["price"]["leaves_out"] = json!(["whatever"]))), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:statevector")["price"]["money"] = json!({ "free": false }))), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:statevector")["outcome"] = json!("best"))), + // A heuristic claimed to meet exact, a rejection for another reason, a + // route claimed to meet what it does not. + (&[PLANNER_ROUTE], Box::new(|b| { let r = at(b, "method:mps"); r["outcome"] = json!("met"); r.as_object_mut().unwrap().shift_remove("rejected"); })), + (&[PLANNER_ROUTE], Box::new(|b| at(b, "method:mps")["rejected"]["code"] = json!("deadline"))), + (&[PLANNER_ROUTE, PLANNER_CHOICE], Box::new(|b| { let r = at(b, "method:statevector"); r["outcome"] = json!("rejected"); r["rejected"] = json!({ "code": "deadline", "why": "too slow" }); b["result"]["planner"]["choice"] = json!("method:cutrank"); let c = at(b, "method:cutrank"); c["outcome"] = json!("chosen"); c.as_object_mut().unwrap().shift_remove("rejected"); })), + // A price changed, which the digest covers, and the rule still picks it. + (&[PLANNER_STABLE], Box::new(|b| at(b, "method:statevector")["price"]["memory_bytes"] = json!(1u64 << 29))), + // Past the contract by what it states of itself: with no other route, no choice. + (&[PLANNER_ROUTE, PLANNER_CHOICE, PLANNER_STABLE], Box::new(|b| at(b, "method:statevector")["price"]["time"]["seconds"] = json!(31.0))), + (&[PLANNER_ROUTE, PLANNER_CHOICE, PLANNER_STABLE], Box::new(|b| at(b, "method:statevector")["price"]["time"] = json!({ "seconds": null, "why": "not known" }))), + (&[PLANNER_ROUTE, PLANNER_CHOICE, PLANNER_STABLE], Box::new(|b| at(b, "method:statevector")["price"]["memory_bytes"] = json!(1u64 << 40))), + (&[PLANNER_CHOICE], Box::new(|b| b["result"]["method"] = json!("mps"))), + (&[PLANNER_STABLE], Box::new(|b| b["result"]["planner"]["stable"]["digest"] = json!("00".repeat(32)))), + (&[PLANNER_STABLE], Box::new(|b| b["result"]["planner"]["stable"]["choice"] = json!(false))), + (&[PLANNER_STABLE], Box::new(|b| b["result"]["planner"]["stable"]["routes"] = json!([]))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["deadline"]["kept"] = json!(false))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["deadline"]["elapsed_ms"] = json!(999_999))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["deadline"]["seconds"] = json!(60))), + (&[PLANNER_KEPT], Box::new(|b| { b["result"]["planner"]["kept"].as_object_mut().unwrap().shift_remove("cost"); })), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["energy"] = json!({ "max_joules": 1, "joules": null, "kept": null }))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["cost"]["kept"] = json!(false))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["elapsed_ms"] = json!(999_999))), + (&[CONTRACT_CLASS], Box::new(|b| b["result"]["accuracy"]["class"] = json!("heuristic"))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"] = json!({ "ran": false, "code": "none", "why": "no provider answered" }))), + ]; + for (want, edit) in cases { + let body = resealed(&good, edit); + let mut want = want.to_vec(); + want.sort_unstable(); + assert_eq!(reasons(&body), want, "{}", body["result"]["planner"]); + } + // Another route that meets the contract chosen and run, when the rule picks + // the cheaper: the choice alone is wrong. + let two = seal_local(&json!({ "qasm": BELL, "shots": 100, "contract": { "exactness": "exact" } })); + assert_eq!(two["result"]["planner"]["choice"], "method:stabilizer"); + let dearer = resealed(&two, |b| { + at(b, "method:stabilizer")["outcome"] = json!("met"); + at(b, "method:statevector")["outcome"] = json!("chosen"); + b["result"]["planner"]["choice"] = json!("method:statevector"); + b["result"]["method"] = json!("statevector"); + }); + assert_eq!(reasons(&dearer), vec![PLANNER_CHOICE]); + // A missed deadline is the truth stated, and valid. + let missed_it = resealed(&good, |b| { + b["result"]["elapsed_ms"] = json!(31_000); + b["result"]["planner"]["kept"]["deadline"]["elapsed_ms"] = json!(31_000); + b["result"]["planner"]["kept"]["deadline"]["kept"] = json!(false); + }); + assert_eq!(reasons(&missed_it), Vec::<&str>::new()); + assert!(missed(&missed_it["result"])); + assert!(!missed(&good["result"])); + // No contract, and yet a reasoning. + let plain = seal_local(&json!({ "qasm": ROT, "shots": 100 })); + assert_eq!(reasons(&resealed(&plain, |b| b["result"]["planner"] = good["result"]["planner"].clone())), vec![PLANNER_FORM]); + assert_eq!(reasons(&resealed(&plain, |b| b["result"]["shadow"] = json!({ "ran": false }))), vec![SHADOW]); + assert_eq!(reasons(&plain), Vec::<&str>::new()); +} + +/// A provider's result under a contract, as a host seals it. +fn provider_body(req: &Value, quotes: Vec, counts: Vec) -> Value { + provider_body_on(req, quotes, counts, "silicon", false) +} + +fn provider_body_on(req: &Value, quotes: Vec, counts: Vec, provenance: &str, approximate: bool) -> Value { + let d = decide(reg(), req, &Host::new(GIB).with_quotes(quotes)).unwrap(); + let Choice::Provider(name) = d.choice else { panic!("a local route was chosen: {}", d.reasoning) }; + let read = provider::read_named(req, Some(&name)).unwrap(); + let text = "OPENQASM 3.0;\nbit[2] c;\ncz $0, $1;\n"; + // Who ran it and what it cost, as the route chosen says: what ran is what was chosen. + let chosen = route(&d.reasoning, &format!("provider:{name}")).clone(); + let money = &chosen["price"]["money"]; + let cost = if money["free"] == true { + json!({ "free": true, "estimate": { "free": true }, "charged": null, "confirmed": false }) + } else { + let mut estimate = money.clone(); + estimate.as_object_mut().unwrap().remove("unknown"); + json!({ "free": false, "estimate": estimate, "charged": { "amount": money["amount"], "currency": money["currency"] }, "confirmed": true }) + }; + let m = provider::Measured { + counts, + provider: json!({ "name": name, "kind": "process", "protocol": "wai.quantum.provider/1", "device": chosen["device"], "provenance": provenance, "qubits": 5, "basis": "rzsxxcz", "describe": "ab".repeat(32) }), + calibration: Some("snap-1".into()), + compiled: json!({ "basis": "rzsxxcz", "program": blake3::hash(text.as_bytes()).to_hex().to_string(), "qasm3": text, "native_gates": 9, "two_qubit_gates": 1, "swaps": 0, "layout": [0, 1], "final_layout": [0, 1], "checked": "checked here" }), + job: json!({ "id": "j-1", "polls": 0 }), + cost, + energy: json!({ "unmetered": "the work ran at the provider" }), + }; + let e = provider::provider_execution(&json!({ "mitigation": "none", "twirling": "none", "decoder": "none", "decoupling": "none", "remapping": "none", "optimisation": "none", "verbatim": true })); + let e = e.unwrap_or_else(|_| provider::provider_execution(&json!({ "mitigation": "none", "twirling": "none", "decoupling": "none", "remapping": "none", "optimisation": "none", "verbatim": true })).unwrap()); + let mut result = provider::result_stated(&read, m, &provider::Statement::new(provider::CountsSource::Shots, e).approximate(approximate)).unwrap(); + seal_provider(reg(), req, &mut result, &d.reasoning, Some(12_000)).unwrap(); + provider::seal(req, result, &SigningKey::from_bytes(&[9; 32]), "on lab") +} + +fn device_contract() -> Value { + json!({ "qasm": BELL, "shots": 1000, "seed": 7, "contract": { "exactness": "measured", "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" }, "deadline_seconds": 300 } }) +} + +/// A provider's answer has a classical method's beside it, by the strongest class +/// that can reach it, and their distance, which anyone recomputes from the two. +#[test] +fn a_provider_s_answer_is_shadowed_and_both_are_sealed_with_their_distance() { + let req = device_contract(); + let body = provider_body(&req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + let c = job::check(&body); + assert!(c.valid(), "{:?}\n{}", c.reasons, body["result"]); + let r = &body["result"]; + let s = &r["shadow"]; + assert_eq!((s["ran"].as_bool(), s["route"].as_str()), (Some(true), Some("method:exact")), "{s}"); + assert_eq!(s["accuracy"]["class"], "bit-exact"); + // Sampled on a stream of its own, and of the same shots. + assert_eq!((s["request"]["seed"].as_u64(), s["request"]["shots"].as_u64()), (Some(7 + (1 << 32)), Some(1000)), "{s}"); + assert_eq!(s["request"]["qasm"], BELL); + assert_eq!(r["planner"]["shadow"]["route"], "method:exact"); + assert_eq!(r["planner"]["shadow"]["budget_seconds"].as_f64(), Some(288.0), "what the deadline leaves after the provider's own time"); + // The distance from the counts, by hand: the shadow's split is its own. + let (a, b) = (r["counts"].as_object().unwrap(), s["counts"].as_object().unwrap()); + let shadow_00 = b["00"].as_u64().unwrap(); + let shadow_11 = b["11"].as_u64().unwrap(); + assert_eq!(shadow_00 + shadow_11, 1000, "the circuit gives no other outcome: {b:?}"); + let want = shadow_00.abs_diff(450) + shadow_11.abs_diff(450) + 100; + assert_eq!(s["distance"]["numerator"].as_u64(), Some(want)); + assert_eq!(s["distance"]["denominator"], 2000); + assert_eq!(s["distance"]["total_variation"].as_f64(), Some(want as f64 / 2000.0)); + assert_eq!(a["01"], 100); + let root = ((450 * shadow_00) as f64).sqrt() + ((450 * shadow_11) as f64).sqrt(); + assert_eq!(s["distance"]["hellinger_fidelity"].as_f64(), Some(root * root / 1e6)); + // The same again: the shadow is the only part of a provider's result that is. + let again = provider_body(&req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + assert_eq!(again["result"]["shadow"]["counts"], s["counts"]); + let rc = recheck(reg(), &body).unwrap(); + assert_eq!((rc["holds"].as_bool(), rc["shadow"]["same"].as_bool()), (Some(true), Some(true)), "{rc}"); + let mut forged = body.clone(); + forged["result"]["shadow"]["counts"]["00"] = json!(shadow_00 + 1); + forged["result"]["shadow"]["counts"]["11"] = json!(shadow_11 - 1); + assert_eq!(recheck(reg(), &forged).unwrap()["holds"], false); + // What it kept, stated. + let kept = &r["planner"]["kept"]; + assert_eq!((kept["deadline"]["elapsed_ms"].as_u64(), kept["deadline"]["kept"].as_bool(), kept["cost"]["kept"].as_bool()), (Some(12_000), Some(true), Some(true)), "{kept}"); + // A request that names no provider verifies by the planner's choice, and one + // that does by its own. + assert_eq!(r["provider"]["name"], "qpu"); + let mut named = req.clone(); + named["provider"] = json!("qpu"); + assert!(job::check(&provider_body(&named, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![500, 0, 0, 500])).valid()); + // A Clifford circuit wider than any state: the tableau shadows it. + let ghz = format!("OPENQASM 3.0;\nqubit[60] q;\nbit[60] c;\nh q[0];\n{}c = measure q;\n", (1..60).map(|i| format!("cx q[0], q[{i}];\n")).collect::()); + let wide_req = json!({ "qasm": ghz, "shots": 100, "contract": { "exactness": "measured", "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } } }); + let c = decided(&wide_req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))]); + assert_eq!(c.reasoning["shadow"]["route"], "method:stabilizer", "{}", c.reasoning["shadow"]); + assert_eq!(c.reasoning["shadow"]["budget_seconds"].as_f64(), Some(SHADOW_MAX_SECONDS)); +} + +/// When no classical method can reach the same answer within the contract, the +/// result says so and why: the provider's answer stands, and stands alone. +#[test] +fn when_no_shadow_was_possible_the_result_says_so_and_why() { + // The deadline leaves it no time. + let mut req = device_contract(); + req["contract"]["deadline_seconds"] = json!(12); + let body = provider_body(&req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![500, 0, 0, 500]); + let s = &body["result"]["shadow"]; + assert_eq!((s["ran"].as_bool(), s["code"].as_str()), (Some(false), Some("budget")), "{s}"); + assert!(s["why"].as_str().unwrap().contains("0 s"), "{s}"); + assert!(body["result"]["planner"]["shadow"]["route"].is_null()); + assert!(body["result"]["planner"]["shadow"]["tried"].as_array().unwrap().iter().any(|t| t["route"] == "method:stabilizer" && t["code"] == "budget"), "{s}"); + assert!(s.get("counts").is_none()); + assert!(job::check(&body).valid(), "{:?}", job::check(&body).reasons); + let rc = recheck(reg(), &body).unwrap(); + // No shadow can be planned here either, so what the reasoning says is what holds. + assert_eq!((rc["holds"].as_bool(), rc["shadow"]["checked"].as_bool(), rc["shadow"]["same"].as_bool()), (Some(true), Some(true), Some(true)), "{rc}"); + // No memory: on a host with less than any method's margin. + let host = Host::new(1 << 20).with_quotes(vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))]); + let c = consider(reg(), &device_contract(), &host).unwrap(); + assert_eq!(c.reasoning["shadow"]["code"], "memory", "{}", c.reasoning["shadow"]); + // Nothing takes it: the seed too wide for a tableau's reach is not the case + // for a provider's dyadic program, so a method's run failing says that. + let reasoning = json!({ "shadow": { "route": "method:exact", "request": { "qasm": "not a program", "shots": 1, "seed": 1, "method": "exact" } }, "host": { "job_bytes": GIB } }); + let s = shadow(reg(), &reasoning, &json!({ "shots": 1, "counts": { "0": 1 }, "omitted_shots": 0 })); + assert_eq!((s["ran"].as_bool(), s["code"].as_str()), (Some(false), Some("failed")), "{s}"); +} + +/// Each rule of a provider's contract job, broken once and found alone. +#[test] +fn every_rule_a_verifier_holds_a_provider_s_contract_job_to_is_broken_once_and_found_alone() { + let req = device_contract(); + let good = provider_body(&req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0)), quote("sim", "simulator:a state vector", json!({ "free": true }), Some(0.0))], vec![450, 100, 0, 450]); + assert_eq!(reasons(&good), Vec::<&str>::new(), "{}", good["result"]["planner"]); + type Edit = Box; + let cases: Vec<(&[&str], Edit)> = vec![ + (&[SHADOW], Box::new(|b| { b["result"].as_object_mut().unwrap().shift_remove("shadow"); })), + (&[SHADOW], Box::new(|b| { b["result"]["planner"].as_object_mut().unwrap().shift_remove("shadow"); })), + (&[SHADOW], Box::new(|b| { let n = b["result"]["shadow"]["distance"]["numerator"].as_u64().unwrap(); b["result"]["shadow"]["distance"]["numerator"] = json!(n + 1); })), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["distance"]["total_variation"] = json!(0.0))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["distance"]["hellinger_fidelity"] = json!(1.0))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["distance"]["sampling_tvd_bound"] = json!(0.0))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["distance"] = json!({ "computed": false }))), + // Not computed, with every shot listed on both sides: it could have been. + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["distance"] = json!({ "computed": false, "why": "said so" }))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["omitted_shots"] = json!(1))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["route"] = json!("method:statevector"))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["request"]["seed"] = json!(7))), + (&[SHADOW], Box::new(|b| { b["result"]["shadow"]["request"]["seed"] = json!(7); b["result"]["planner"]["shadow"]["request"]["seed"] = json!(7); })), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["request"]["qasm"] = json!("OPENQASM 3.0;"))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"] = json!({ "ran": false }))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"] = json!({ "ran": false, "code": "none", "why": "says none, and its plan had one" }))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"] = json!("no"))), + // A provider the planner did not choose answered. + (&[PLANNER_CHOICE, "request_provider"], Box::new(|b| b["result"]["provider"]["name"] = json!("sim"))), + // The simulator is claimed to meet what wants a device. + (&[PLANNER_ROUTE], Box::new(|b| { let r = at(b, "provider:sim"); r["outcome"] = json!("met"); r.as_object_mut().unwrap().shift_remove("rejected"); })), + // A cost past the ceiling, or a provider's time past the deadline, claimed to meet it. + (&[PLANNER_ROUTE, PLANNER_CHOICE], Box::new(|b| at(b, "provider:qpu")["price"]["money"]["amount"] = json!("1.01"))), + (&[PLANNER_ROUTE, PLANNER_CHOICE], Box::new(|b| at(b, "provider:qpu")["price"]["money"]["currency"] = json!("EUR"))), + (&[PLANNER_ROUTE, PLANNER_CHOICE], Box::new(|b| at(b, "provider:qpu")["price"]["money"] = json!({ "free": false, "unknown": "not said" }))), + // The least it can come to, under the ceiling, claimed to meet it. + (&[PLANNER_ROUTE, PLANNER_CHOICE], Box::new(|b| at(b, "provider:qpu")["price"]["money"]["at_least"] = json!(true))), + (&[PLANNER_FORM], Box::new(|b| at(b, "provider:qpu")["price"]["money"]["at_least"] = json!(false))), + // The shadow's budget is what the deadline leaves after the provider's time, so + // its plan no longer says what the contract leaves it. + (&[PLANNER_ROUTE, PLANNER_CHOICE, SHADOW], Box::new(|b| at(b, "provider:qpu")["price"]["time"]["seconds"] = json!(301.0))), + (&[PLANNER_ROUTE, PLANNER_CHOICE, SHADOW], Box::new(|b| at(b, "provider:qpu")["price"]["time"] = json!({ "seconds": null, "why": "not said" }))), + // A device's class that is not its provenance's. + (&[CONTRACT_CLASS, "provider_class"], Box::new(|b| b["result"]["accuracy"]["class"] = json!("simulated"))), + // Charged past the ceiling, and kept said to hold. + (&[PLANNER_KEPT], Box::new(|b| b["result"]["cost"]["charged"]["amount"] = json!("1.5"))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["cost"]["max_cost"]["amount"] = json!("100"))), + ]; + for (want, edit) in cases { + let body = resealed(&good, edit); + let mut want = want.to_vec(); + want.sort_unstable(); + assert_eq!(reasons(&body), want, "{}", body["result"]["shadow"]); + } + // An omitted_shots of 0 is 0 however it is written. + let spelt = resealed(&good, |b| b["result"]["shadow"]["omitted_shots"] = json!(0.0)); + assert_eq!(reasons(&spelt), Vec::<&str>::new()); + // Charged past the ceiling, stated: valid, and it says it missed. + let over = resealed(&good, |b| { + b["result"]["cost"]["charged"]["amount"] = json!("1.5"); + b["result"]["planner"]["kept"]["cost"]["charged"]["amount"] = json!("1.5"); + b["result"]["planner"]["kept"]["cost"]["kept"] = json!(false); + }); + assert_eq!(reasons(&over), Vec::<&str>::new()); + assert!(missed(&over["result"])); + // No contract's planner to name it, and the request names none. + let unnamed = resealed(&good, |b| { b["request"].as_object_mut().unwrap().shift_remove("contract"); }); + assert!(reasons(&unnamed).contains(&"request_provider"), "{:?}", reasons(&unnamed)); + // Without providers allowed, the planner's choice does not name it either. + let not_allowed = resealed(&good, |b| { b["request"]["contract"].as_object_mut().unwrap().shift_remove("providers"); }); + assert!(reasons(¬_allowed).contains(&"request_provider"), "{:?}", reasons(¬_allowed)); +} + +/// What a local route costs is one set of bytes on every host, and the digest +/// pins it: this test runs on each host and each architecture CI has. +#[test] +fn what_the_routes_cost_is_the_same_bytes_on_every_host() { + let jobs: [(Value, u64); 5] = [ + (json!({ "qasm": BELL, "shots": 1000, "contract": { "exactness": "exact" } }), GIB), + (json!({ "qasm": ROT, "shots": 100, "observables": ["Z0 Z1"], "contract": { "exactness": "exact" } }), GIB), + (json!({ "qasm": wide(40), "shots": 10, "contract": { "exactness": "heuristic" } }), 8 * GIB), + (json!({ "qasm": "OPENQASM 3.0;\nqubit[8] q;\nh q;\ncx q[0], q[1];\ncx q[1], q[2];\nrz(0.3) q[0];\nrx(0.2) q[2];\n", "shots": 50, "contract": { "exactness": "exact" } }), GIB), + (json!({ "qasm": BELL, "shots": 100, "noise": { "depolarizing_2q": 0.02 }, "contract": { "exactness": "exact" } }), GIB), + ]; + let got: Vec = jobs.iter().map(|(req, cap)| considered(req, *cap).reasoning["stable"]["digest"].as_str().unwrap().to_string()).collect(); + for (i, (req, cap)) in jobs.iter().enumerate() { + assert_eq!(got[i], PINNED_DIGESTS[i], "{req}: every digest now: {got:?}"); + // Heuristic takes what a GPU's single precision gives, so that choice is the host's. + assert_eq!(considered(req, *cap).reasoning["stable"]["choice"], i != 2, "{req}"); + } + // A GPU's route is the host's, and not among what the digest covers. + let c = considered(&jobs[0].0, GIB); + let covered = c.reasoning["stable"]["routes"].as_array().unwrap(); + assert!(!covered.contains(&json!("method:statevector_single")) && !covered.contains(&json!("method:cutrank_single")) && covered.contains(&json!("method:stabilizer")), "{covered:?}"); + // Asking for what a GPU could give makes the choice the host's. + let single = considered(&json!({ "qasm": ROT, "shots": 10, "contract": { "exactness": "single" } }), GIB); + assert_eq!(single.reasoning["stable"]["choice"], false); + // Allowing a provider does too, though this host has none. + assert_eq!(considered(&json!({ "qasm": BELL, "shots": 10, "contract": { "providers": "allowed" } }), GIB).reasoning["stable"]["choice"], false); + // And a local job can be priced again, here, to the sealed digest. + let body = seal_local(&jobs[0].0); + let rc = recheck(reg(), &body).unwrap(); + assert_eq!((rc["holds"].as_bool(), rc["priced"]["same"].as_bool()), (Some(true), Some(true)), "{rc}"); + let forged = resealed(&body, |b| b["result"]["planner"]["stable"]["digest"] = json!("00".repeat(32))); + assert_eq!(recheck(reg(), &forged).unwrap()["holds"], false); +} + +const PINNED_DIGESTS: [&str; 5] = [ + "9e40eeb50e1fd3cea81119ec7c5d4ee1517c46aa35acf13270658e745058dc92", + "221e18db5ede946e533ef17725a1cb2551ed53120cf2b52a874cfa043e9c0aba", + "967b86c71cc874b2e9b1850df12b7e6d2db87c71a2e60af6514a459c05c59088", + "c8876fea57d73b89744656a66b09b78558a50f08581eb2b2b8cac6331e121c8d", + "8189fad98f54c33e6956f82c5d4f7d9bd2c46a7ad49ebb08f0bdbf003cb1d323", +]; + +/// Compile, repair, intent and noise pass through: a contract is what is asked of +/// the method, and the job's other members stay what they are. +#[test] +fn the_job_s_other_members_run_as_they_do_under_a_contract() { + // A compiled job's class is of the compiled program, and the result says how far. + let compiled = seal_local(&json!({ "qasm": "OPENQASM 3.0;\nqubit q;\nrx(0.4) q;\n", "shots": 20, "compile": { "epsilon": 0.001 }, "contract": { "exactness": "exact" } })); + assert!(compiled["result"].get("compiled").is_some()); + assert!(job::check(&compiled).valid(), "{:?}", job::check(&compiled).reasons); + // An intent is checked, with its memory in the price. + let intent = json!({ "distribution": { "00": 0.5, "11": 0.5 } }); + let body = seal_local(&json!({ "qasm": BELL, "shots": 50, "intent": intent, "contract": { "exactness": "exact" } })); + assert_eq!(body["result"]["verdict"]["holds"], true); + assert!(job::check(&body).valid()); + // Under noise, the classes are what the noise leaves. + let noisy = considered(&json!({ "qasm": BELL, "shots": 10, "noise": { "depolarizing_2q": 0.01 }, "contract": { "exactness": "exact" } }), GIB); + assert_eq!(noisy.reasoning["choice"], "method:density_matrix"); + assert_eq!(route(&noisy.reasoning, "method:stabilizer")["class"], "estimate"); + assert_eq!(code(&noisy.reasoning, "method:stabilizer"), Some("class")); + // A device target's job has its one route, held to the contract. + let on_target = json!({ "qasm": BELL, "shots": 50, "target": "synthetic-line-5", "contract": {} }); + let body = seal_local(&on_target); + assert_eq!(body["result"]["planner"]["routes"].as_array().unwrap().len(), 1); + assert_eq!(body["result"]["planner"]["wanted_from"], "named"); + assert!(job::check(&body).valid(), "{:?}", job::check(&body).reasons); + let e = catalog::plan(&json!({ "qasm": BELL, "shots": 50, "target": "synthetic-line-5", "contract": { "exactness": "measured" } }), GIB).unwrap_err(); + assert!(e.ends_with("[J071]"), "{e}"); + // A pulse job's bound is held the same way: its class is bounded, not exact. + let pulse = "OPENQASM 3.0;\ndefcalgrammar \"openpulse\";\ncal {\n port d0;\n frame f0 = newframe(d0, 5e9, 0);\n waveform w = gaussian(0.1, 16dt, 4dt);\n}\ndefcal x $0 {\n play(f0, w);\n}\nx $0;\n"; + let asked = json!({ "qasm": pulse, "method": "pulse", "contract": { "exactness": "exact" } }); + let e = catalog::plan(&asked, GIB).unwrap_err(); + assert!(e.ends_with("[J071]") && e.contains("its class is bounded"), "{e}"); + let c = considered(&json!({ "qasm": pulse, "method": "pulse", "contract": { "exactness": "bounded" } }), GIB); + assert_eq!((c.reasoning["choice"].as_str(), c.reasoning["routes"].as_array().map(Vec::len)), (Some("method:pulse"), Some(1)), "{}", c.reasoning); + // On the fabric: a member asked for leaves only the state vector's route. + let c = considered(&json!({ "qasm": BELL, "shots": 10, "fabric": "cpu", "contract": {} }), GIB); + assert_eq!(c.reasoning["choice"], "method:stabilizer"); + assert_eq!(code(&c.reasoning, "method:statevector_single"), Some("fabric")); +} + +/// A method that declares two classes neither of which meets the other. +struct TwoWays; + +impl Method for TwoWays { + fn name(&self) -> &str { + "two_ways" + } + fn version(&self) -> &str { + "0.1.0" + } + fn classes(&self) -> Vec { + vec!["single".into(), "bounded".into()] + } + fn descriptor(&self) -> Value { + json!({ "circuits": "any", "answers": ["counts"] }) + } + fn plan(&self, job: &Job<'_>) -> Result { + let r = job.request()?; + Ok(Plan { method: "two_ways".into(), why: "a test's method".into(), memory_bytes: 1 << 20, work: 1, qubits: r.program.n_qubits, target: None, metered: false }) + } + fn run(&self, job: &Job<'_>, _: &Plan, out: &mut Value) -> Result<(), String> { + let r = job.request()?; + out["accuracy"] = json!({ "class": "single" }); + let mut counts = Map::new(); + counts.insert(r.program.bitstring(|_| false), json!(r.shots)); + out["counts"] = Value::Object(counts); + Ok(()) + } +} + +/// A route's class is one every class its method declares meets: a method that +/// may give single or bounded is heuristic at worst, and a job that keeps its +/// class verifies whichever it gives. The ladder by strength said bounded, and a +/// single result then broke the receipt its host sealed. +#[test] +fn a_method_that_declares_two_classes_is_held_to_one_both_meet() { + let mut r = Registry::with_builtins(); + r.register(crate::engine::registry::Component::method(TwoWays)).unwrap(); + let req = json!({ "qasm": BELL, "shots": 10, "method": "two_ways", "contract": {} }); + let (p, result) = plan_and_run_in(&r, &req, &Host::new(GIB)).unwrap(); + assert_eq!(route(&result["planner"], "method:two_ways")["class"], "heuristic", "{}", result["planner"]); + assert_eq!(result["planner"]["wanted"], "heuristic"); + let body = job::seal(&req, &p, result, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" })); + assert_eq!(reasons(&body), Vec::<&str>::new()); + // Asked for bounded by name, it is not known to give it. + let e = plan_and_run_in(&r, &json!({ "qasm": BELL, "shots": 10, "method": "two_ways", "contract": { "exactness": "bounded" } }), &Host::new(GIB)).unwrap_err(); + assert!(e.ends_with("[J071]") && e.contains("its class is heuristic"), "{e}"); +} + +/// A result short of what the reasoning wants gives no answer, whether the +/// contract named the class or the job kept auto's: its receipt would not verify. +#[test] +fn a_result_short_of_what_the_reasoning_wants_is_not_completed() { + let reasoning = |w: Value| json!({ "wanted": w, "choice": "method:mps" }); + let heuristic = json!({ "method": "mps", "accuracy": { "class": "heuristic" } }); + let mut r = heuristic.clone(); + let e = complete(&mut r, &reasoning(json!("exact"))).unwrap_err(); + assert!(e.ends_with("[J072]") && r.get("planner").is_none(), "{e}"); + let mut r = heuristic.clone(); + complete(&mut r, &reasoning(json!("heuristic"))).unwrap(); + assert_eq!(r["planner"]["wanted"], "heuristic"); + let mut r = heuristic; + complete(&mut r, &reasoning(Value::Null)).unwrap(); + // An approximate simulator's counts fall short of a simulator's the contract names, + // and not of the class a named simulator keeps. + let approximate = json!({ "method": "provider", "accuracy": { "class": "simulated", "approximate": true } }); + let mut r = approximate.clone(); + assert!(complete(&mut r, &json!({ "wanted": "simulated", "wanted_from": "contract", "choice": "provider:sim" })).unwrap_err().ends_with("[J072]")); + let mut r = approximate; + complete(&mut r, &json!({ "wanted": "simulated", "wanted_from": "named", "choice": "provider:sim" })).unwrap(); +} + +/// The distance is exact where it sums whole numbers and a double's elsewhere, +/// however many the shots: a product of two counts is never taken in a machine +/// word that wraps. +#[test] +fn the_distance_holds_at_the_largest_shots() { + let s: u64 = (1 << 53) - 1; + let a = json!({ "0": s }); + let b = json!({ "0": s - 2, "1": 2 }); + let d = distance(&a, &b, s).unwrap(); + assert_eq!(d["numerator"], 4); + assert!(d["denominator"].is_f64(), "2·S past 2^53 − 1 is written as a double: {d}"); + assert_eq!(d["denominator"].as_f64(), Some(2.0 * s as f64)); + let root = ((s as f64) * ((s - 2) as f64)).sqrt(); + assert_eq!(d["hellinger_fidelity"].as_f64(), Some(root * root / ((s as f64) * (s as f64)))); + assert_eq!(d["total_variation"].as_f64(), Some(4.0 / (2.0 * s as f64))); + // No shots, no distance; and counts past the shots leave none either. + assert!(distance(&a, &b, 0).is_none()); + assert!(distance(&json!({ "0": 10 }), &json!({ "0": 10 }), 3).is_none()); +} + +fn cases(good: &Value, cases: Vec<(&[&'static str], Box)>) { + for (i, (want, edit)) in cases.into_iter().enumerate() { + let body = resealed(good, edit); + let mut want = want.to_vec(); + want.sort_unstable(); + assert_eq!(reasons(&body), want, "case {i}: {}\n{}", body["result"]["shadow"], body["result"]["planner"]["shadow"]); + } +} + +/// A shadow is a classical method's run of exactly the job's program, its +/// shots and its own seed: not the provider's own counts, not a run with no +/// route planned, not one under a noise model the job never asked for, whole +/// counts that sum to the shots exactly, and a plan whose class, budget and +/// price are what the contract leaves. +#[test] +fn a_shadow_is_a_method_s_run_of_exactly_the_job_s_program() { + let req = device_contract(); + let good = provider_body(&req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + assert_eq!(reasons(&good), Vec::<&str>::new()); + cases(&good, vec![ + // The provider as its own shadow, its counts at distance 0. + (&[SHADOW], Box::new(|b| { + for side in ["/result/planner/shadow", "/result/shadow"] { + let s = b.pointer_mut(side).unwrap(); + s["route"] = json!("provider:qpu"); + s["request"].as_object_mut().unwrap().shift_remove("method"); + } + let counts = b["result"]["counts"].clone(); + b["result"]["shadow"]["counts"] = counts.clone(); + b["result"]["shadow"]["distance"] = distance(&counts, &counts, 1000).unwrap(); + })), + // Run, where no route was planned. + (&[SHADOW], Box::new(|b| { + let req = b["result"]["planner"]["shadow"]["request"].clone(); + b["result"]["planner"]["shadow"] = json!({ "route": null, "code": "none", "why": "said so", "request": req }); + b["result"]["shadow"]["route"] = Value::Null; + })), + // A noise model the job never asked for, on both sides. + (&[SHADOW], Box::new(|b| { + for side in ["/result/planner/shadow/request", "/result/shadow/request"] { + b.pointer_mut(side).unwrap()["noise"] = json!({ "depolarizing_2q": 0.2 }); + } + })), + // A plan that names no route at all, null or otherwise, and why none ran. + (&[SHADOW], Box::new(|b| { + b["result"]["planner"]["shadow"] = json!({ "code": "none", "why": "said so" }); + b["result"]["shadow"] = json!({ "ran": false, "code": "none", "why": "said so" }); + })), + // A plan's code that no plan has, and a failure where none was planned. + (&[SHADOW], Box::new(|b| { + b["result"]["planner"]["shadow"] = json!({ "route": null, "code": "failed", "why": "said so" }); + b["result"]["shadow"] = json!({ "ran": false, "code": "failed", "why": "said so" }); + })), + (&[SHADOW], Box::new(|b| b["result"]["planner"]["shadow"]["class"] = json!("measured"))), + // A class the ladder has, and not the one its route is listed with. + (&[SHADOW], Box::new(|b| b["result"]["planner"]["shadow"]["class"] = json!("heuristic"))), + (&[SHADOW], Box::new(|b| b["result"]["planner"]["shadow"]["budget_seconds"] = json!(300.0))), + (&[SHADOW], Box::new(|b| b["result"]["planner"]["shadow"]["price"]["time"]["seconds"] = json!(289.0))), + // Counts a shot short of the shots, their distance what they give. + (&[SHADOW], Box::new(|b| { + let n = b["result"]["shadow"]["counts"]["00"].as_u64().unwrap(); + b["result"]["shadow"]["counts"]["00"] = json!(n - 1); + let (counts, shadow) = (b["result"]["counts"].clone(), b["result"]["shadow"]["counts"].clone()); + b["result"]["shadow"]["distance"] = distance(&counts, &shadow, 1000).unwrap(); + })), + // Counts that are not whole, or not at least 1, or sum to the shots only as doubles. + (&[SHADOW], Box::new(|b| { + let n = b["result"]["shadow"]["counts"]["00"].as_u64().unwrap(); + b["result"]["shadow"]["counts"]["00"] = json!(n as f64); + })), + (&[SHADOW], Box::new(|b| { + let n = b["result"]["shadow"]["counts"]["00"].as_u64().unwrap(); + b["result"]["shadow"]["counts"]["00"] = json!(n + 1); + b["result"]["shadow"]["counts"]["01"] = json!(-1); + })), + (&[SHADOW], Box::new(|b| { + let n = b["result"]["shadow"]["counts"]["00"].as_u64().unwrap(); + b["result"]["shadow"]["counts"]["00"] = json!(1e16); + b["result"]["shadow"]["counts"]["01"] = json!(-1e16); + b["result"]["shadow"]["counts"]["10"] = json!(n); + })), + // A class short of the plan's. + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["accuracy"]["class"] = json!("heuristic"))), + ]); +} + +/// A host that says its shadow failed is held to it: run here, the shadow it +/// planned runs, and the recheck says so. +#[test] +fn a_shadow_the_host_says_failed_is_run_again() { + let req = device_contract(); + let good = provider_body(&req, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + let said = resealed(&good, |b| b["result"]["shadow"] = json!({ "ran": false, "code": "failed", "why": "it did not finish" })); + assert_eq!(reasons(&said), Vec::<&str>::new(), "a failure is the host's word"); + let rc = recheck(reg(), &said).unwrap(); + assert_eq!((rc["holds"].as_bool(), rc["shadow"]["same"].as_bool()), (Some(false), Some(false)), "{rc}"); +} + +/// Under a contract a provider is used only where it allows one: `never` is the +/// default, so a job that names one under any other contract is refused, and a +/// receipt that says otherwise does not verify. +#[test] +fn under_a_contract_a_provider_is_used_only_where_it_allows_one() { + let host = Host::new(GIB).with_quotes(vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))]); + for c in [json!({}), json!({ "providers": "never" }), json!({ "deadline_seconds": 60 })] { + let e = consider(reg(), &json!({ "qasm": BELL, "provider": "qpu", "contract": c }), &host).unwrap_err(); + assert_eq!(refusal::codes_in(&e), ["J070"], "{c}: {e}"); + } + let mut named = device_contract(); + named["provider"] = json!("qpu"); + let good = provider_body(&named, vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![500, 0, 0, 500]); + assert_eq!(reasons(&good), Vec::<&str>::new()); + for edit in [json!("never"), Value::Null] { + let under = resealed(&good, |b| b["request"]["contract"]["providers"] = edit.clone()); + assert_eq!(reasons(&under), vec![CONTRACT_PROVIDER, PLANNER_CHOICE, PLANNER_ROUTE], "{edit}"); + } +} + +/// What a price may state is bounded: a provider's estimate past the bounds is +/// an unknown, a receipt stating one does not verify, and a ceiling past them +/// does not read. +#[test] +fn what_a_price_may_state_is_bounded_and_past_it_is_an_unknown() { + let long = format!("0.{}1", "0".repeat(70)); + let req = json!({ "qasm": BELL, "shots": 1000, "contract": { "exactness": "measured", "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } } }); + let c = decided(&req, vec![quote("qpu", "silicon", json!({ "free": false, "amount": long, "currency": "USD" }), Some(1e306))]); + let r = route(&c.reasoning, "provider:qpu"); + assert!(r["price"]["time"]["seconds"].is_null() && r["price"]["time"]["why"].as_str().unwrap().contains("past"), "{r}"); + assert!(r["price"]["money"]["unknown"].as_str().unwrap().contains("64"), "{r}"); + assert_eq!(code(&c.reasoning, "provider:qpu"), Some("cost_unknown")); + let good = provider_body(&device_contract(), vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![500, 0, 0, 500]); + cases(&good, vec![ + (&[PLANNER_FORM], Box::new(|b| at(b, "provider:qpu")["price"]["time"]["seconds"] = json!(1e306))), + (&[PLANNER_FORM], Box::new(|b| at(b, "provider:qpu")["price"]["money"]["amount"] = json!("1".repeat(65)))), + ]); + let e = catalog::plan(&json!({ "qasm": BELL, "contract": { "max_cost": { "amount": "1".repeat(65), "currency": "USD" } } }), GIB).unwrap_err(); + assert!(e.ends_with("[J070]"), "{e}"); +} + +/// A local route costs no money, and `kept` states exactly what the contract +/// and the result give: the charge the result states, and no other member. +#[test] +fn a_local_route_is_free_and_kept_states_exactly_the_charge() { + let local = seal_local(&json!({ "qasm": ROT, "shots": 100, "contract": { "exactness": "exact", "deadline_seconds": 30, "max_cost": { "amount": "1", "currency": "USD" } } })); + cases(&local, vec![ + (&[PLANNER_FORM], Box::new(|b| at(b, "method:statevector")["price"]["money"] = json!({ "free": false, "amount": "1", "currency": "USD" }))), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:mps")["price"]["money"] = json!({ "free": false, "unknown": "a host's word" }))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["deadline"]["note"] = json!("x"))), + ]); + let good = provider_body(&device_contract(), vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![500, 0, 0, 500]); + cases(&good, vec![ + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["cost"]["charged"] = json!({ "amount": "0.000001", "currency": "USD" }))), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["cost"]["extra"] = json!(true))), + // A kept that is no boolean does not read as `null`. + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["cost"]["kept"] = json!(0))), + (&[PLANNER_KEPT], Box::new(|b| { + let k = &mut b["result"]["planner"]["kept"]["deadline"]; + k["elapsed_ms"] = Value::Null; + k["kept"] = json!(0); + })), + (&[PLANNER_KEPT], Box::new(|b| b["result"]["planner"]["kept"]["cost"]["max_cost"]["note"] = json!("x"))), + ]); +} + +/// `auto` is recomputed from the routes, the question and each method's rank +/// for it: a host that says auto would pick a heuristic route, to lower the +/// class a contract that names none keeps, is found. +#[test] +fn auto_is_what_the_routes_give_and_cannot_be_lowered() { + let good = seal_local(&json!({ "qasm": ROT, "shots": 100, "contract": { "deadline_seconds": 60 } })); + assert_eq!((good["result"]["planner"]["auto"].as_str(), good["result"]["planner"]["wanted"].as_str()), (Some("method:statevector"), Some("exact"))); + assert_eq!(reasons(&good), Vec::<&str>::new()); + cases(&good, vec![ + // auto said to be mps, the class wanted heuristic, and mps run. + (&[PLANNER_FORM], Box::new(|b| { + let p = &mut b["result"]["planner"]; + p["auto"] = json!("method:mps"); + p["wanted"] = json!("heuristic"); + b["result"]["method"] = json!("mps"); + })), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["question"] = json!("amplitudes"))), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:mps")["auto_rank"] = json!(0))), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["named"] = json!("method:statevector"))), + // auto said to be another route of the same class: the class wanted is as it + // was, and what the routes give is not what is sealed. + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["auto"] = json!("method:cutrank"))), + // A rank that is not the method's, on a route that does not win by it. + (&[PLANNER_FORM], Box::new(|b| at(b, "method:mps")["auto_rank"] = json!(65))), + ]); +} + +/// A device target's job names its one method, whatever else the host brings: +/// its providers are not the job's, and the receipt verifies. +#[test] +fn a_device_target_s_job_names_its_method_beside_the_host_s_providers() { + let req = json!({ "qasm": BELL, "shots": 50, "target": "synthetic-line-5", "contract": { "providers": "allowed", "deadline_seconds": 60 } }); + let host = Host::new(GIB).with_quotes(vec![quote("qpu", "silicon", usd("0.3"), Some(1.0))]); + let (p, result) = plan_and_run_in(reg(), &req, &host).unwrap(); + let r = &result["planner"]; + assert_eq!((r["wanted_from"].as_str(), code(r, "provider:qpu")), (Some("named"), Some("not_named")), "{r}"); + let body = job::seal(&req, &p, result, &SigningKey::from_bytes(&[3; 32]), json!({ "unmetered": "a test" })); + assert_eq!(reasons(&body), Vec::<&str>::new()); +} + +/// A contract that names no class changes nothing a job already meets: an +/// approximate simulator the job names runs under a deadline alone, and only a +/// contract that names `simulated` refuses it. +#[test] +fn a_named_approximate_simulator_runs_under_a_contract_that_names_no_class() { + let mut approx = quote("sim", "simulator:a truncated network", json!({ "free": true }), Some(1.0)); + approx.approximate = true; + let req = json!({ "qasm": BELL, "shots": 1000, "seed": 7, "provider": "sim", "contract": { "providers": "allowed", "deadline_seconds": 60 } }); + let c = decided(&req, vec![approx.clone()]); + assert_eq!((c.reasoning["choice"].as_str(), c.reasoning["wanted"].as_str(), c.reasoning["wanted_from"].as_str()), (Some("provider:sim"), Some("simulated"), Some("named")), "{}", c.reasoning); + let body = provider_body_on(&req, vec![approx.clone()], vec![500, 0, 0, 500], "simulator:a truncated network", true); + assert_eq!(reasons(&body), Vec::<&str>::new()); + let mut asked = req.clone(); + asked["contract"]["exactness"] = json!("simulated"); + assert!(decided(&asked, vec![approx]).refusal.unwrap().ends_with("[J071]")); +} + +/// The sampling bound is at least the total variation two samples of one +/// distribution show on average, sparse or dense: here against seeded draws, +/// among them the case of 65,536 outcomes and 1,000 shots. +#[test] +fn the_sampling_bound_holds_for_sparse_and_dense_outcomes() { + let mut state = 0x9e37_79b9_7f4a_7c15u64; + let mut next = move || { + state = state.wrapping_add(0x9e37_79b9_7f4a_7c15); + let mut z = state; + z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9); + z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb); + z ^ (z >> 31) + }; + for (k, s, trials) in [(2u64, 1000u64, 200), (4, 10, 400), (16, 100, 200), (1024, 1000, 40), (65_536, 1000, 20)] { + let (mut tv, mut bound) = (0.0, 0.0); + for _ in 0..trials { + let mut sample = || { + let mut m = Map::new(); + for _ in 0..s { + let o = format!("{:017b}", next() % k); + let c = m.get(&o).and_then(Value::as_u64).unwrap_or(0); + m.insert(o, json!(c + 1)); + } + Value::Object(m) + }; + let (a, b) = (sample(), sample()); + let d = distance(&a, &b, s).unwrap(); + tv += d["total_variation"].as_f64().unwrap(); + bound += d["sampling_tvd_bound"].as_f64().unwrap(); + } + let (tv, bound) = (tv / trials as f64, bound / trials as f64); + assert!(bound >= 0.99 * tv && bound <= 1.0 && bound <= 1.5 * tv, "{k} outcomes, {s} shots: the mean total variation {tv}, the mean bound {bound}"); + } + // The split's mean deviation, against the binomial's own sum. + for n in [1u128, 2, 3, 4, 5, 10, 11, 100, 1001] { + let want: f64 = (0..=n).map(|b| (2 * b).abs_diff(n) as f64 * binomial(n, b)).sum::() / 2f64.powi(n as i32); + assert!((split_mad(n) - want).abs() <= 1e-9 * want.max(1.0), "{n}: {} {want}", split_mad(n)); + } +} + +fn binomial(n: u128, k: u128) -> f64 { + (0..k).fold(1.0, |c, i| c * (n - i) as f64 / (i + 1) as f64) +} + +/// A provider-named job whose shadow is the stabilizer: its route is listed with +/// the class the shadow has, the reasoning holds before anything is sent, and the +/// receipt a host seals afterwards is one its verifier takes. With the class of an +/// unpriced route, the run would be paid for and its receipt refused. +#[test] +fn a_named_provider_s_routes_carry_the_class_their_shadow_has() { + // 34 qubits of Clifford gates: past exact's and the state vector's memory. + let qasm = format!("OPENQASM 3.0;\nqubit[34] q;\nbit[34] c;\nh q[0];\n{}c = measure q;\n", (0..33).map(|i| format!("cx q[{i}], q[{}];\n", i + 1)).collect::()); + let req = json!({ "qasm": qasm, "shots": 100, "provider": "qpu", "contract": { "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } } }); + let d = decide(reg(), &req, &Host::new(GIB).with_quotes(vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))])).unwrap(); + assert_eq!((d.reasoning["shadow"]["route"].as_str(), d.reasoning["shadow"]["class"].as_str()), (Some("method:stabilizer"), Some("exact")), "{}", d.reasoning["shadow"]); + assert_eq!(route(&d.reasoning, "method:stabilizer")["class"], "exact", "{}", d.reasoning); + before_sending(&req, &d.reasoning, "qpu", 100).unwrap(); + // What is checked before sending is the verifier's own: a shadow that does not + // hold is found while nothing has been spent. + let mut broken = d.reasoning.clone(); + broken["shadow"]["class"] = json!("estimate"); + assert!(before_sending(&req, &broken, "qpu", 100).unwrap_err().contains("shadow")); + // A class the job's memory decides: with room only for a single-precision table, + // cut-rank's route has the class of the plan its shadow would have, not `exact`. + let wide = format!("OPENQASM 3.0;\nqubit[34] q;\nbit[34] c;\nh q[0];\n{}{}c = measure q;\n", (0..33).map(|i| format!("cx q[{i}], q[{}];\n", i + 1)).collect::(), (0..34).map(|i| format!("rx(pi/8) q[{i}];\n")).collect::()); + let req = json!({ "qasm": wide, "shots": 100, "provider": "qpu", "contract": { "providers": "allowed", "max_cost": { "amount": "1", "currency": "USD" } } }); + let (r, _) = catalog::read_in(reg(), &shadow_request(&req).unwrap()).unwrap(); + let pm = catalog::product_measured(&r, false).unwrap(); + let single = catalog::cutrank_bytes(&pm, crate::quantum_cutrank::Precision::Single); + assert!(single < catalog::cutrank_bytes(&pm, crate::quantum_cutrank::Precision::Double)); + let d = decide(reg(), &req, &Host::new(single).with_quotes(vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))])).unwrap(); + assert_eq!(route(&d.reasoning, "method:cutrank")["class"], "single", "{}", d.reasoning); + assert_eq!(d.reasoning["shadow"]["class"], "single", "{}", d.reasoning["shadow"]); + before_sending(&req, &d.reasoning, "qpu", 100).unwrap(); +} + +/// A route states the class its table gives it, and depends on the host only as +/// the rule says; a method's result and a shadow have a class their method has. +#[test] +fn a_built_in_route_and_a_result_are_held_to_their_method_s_classes() { + let local = seal_local(&json!({ "qasm": BELL, "shots": 100, "contract": { "exactness": "exact", "deadline_seconds": 60 } })); + assert_eq!(reasons(&local), Vec::<&str>::new()); + cases(&local, vec![ + // The GPU's single precision, stated exact: a class it never has. + (&[PLANNER_ROUTE], Box::new(|b| at(b, "method:statevector_single")["class"] = json!("exact"))), + // Stated estimate on a job with neither noise nor a target: its class is in + // the digest, and it no longer meets what is wanted. + (&[PLANNER_CHOICE, PLANNER_ROUTE, PLANNER_STABLE], Box::new(|b| at(b, "method:stabilizer")["class"] = json!("estimate"))), + // Out of the digest or into it, by what it says of the host. + (&[PLANNER_ROUTE, PLANNER_STABLE], Box::new(|b| at(b, "method:trajectories")["host_dependent"] = json!(true))), + (&[PLANNER_ROUTE, PLANNER_STABLE], Box::new(|b| at(b, "method:statevector_single")["host_dependent"] = json!(false))), + // A method's result of a class it does not have, whatever is wanted. + (&[CONTRACT_CLASS], Box::new(|b| b["result"]["accuracy"]["class"] = json!("bit-exact"))), + ]); + let noisy = seal_local(&json!({ "qasm": BELL, "shots": 100, "noise": { "depolarizing_2q": 0.01 }, "contract": { "deadline_seconds": 60 } })); + assert_eq!(reasons(&noisy), Vec::<&str>::new()); + assert_eq!(route(&noisy["result"]["planner"], "method:stabilizer")["class"], "estimate"); + let good = provider_body(&device_contract(), vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + cases(&good, vec![ + (&[PLANNER_ROUTE], Box::new(|b| at(b, "provider:qpu")["host_dependent"] = json!(false))), + // A shadow run by a method stated stronger than it is. + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["accuracy"]["class"] = json!("exact"))), + ]); +} + +/// What a route, its host and a shadow state of their form: a method's memory and +/// work are whole numbers and a provider's null, the host's providers are the +/// provider routes, and a shadow's outcomes are a counts' form. +#[test] +fn what_a_receipt_states_of_itself_is_of_its_form() { + // Members alike by value, as the second verifier compares them. + assert!(alike(Some(&json!(7)), Some(&json!(7.0))) && alike(Some(&json!(-0.0)), Some(&json!(0)))); + assert!(!alike(Some(&json!(true)), Some(&json!(1))) && alike(None, Some(&Value::Null)) && !alike(Some(&json!("a")), None)); + assert!(alike(Some(&json!([7])), Some(&json!([7.0]))) && alike(Some(&json!({ "a": -0.0, "b": null })), Some(&json!({ "a": 0 })))); + assert!(!alike(Some(&json!([true])), Some(&json!([1]))) && !alike(Some(&json!({ "a": "x" })), Some(&json!({ "a": "y" })))); + let good = provider_body(&device_contract(), vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + assert_eq!(reasons(&good), Vec::<&str>::new()); + cases(&good, vec![ + (&[PLANNER_FORM], Box::new(|b| at(b, "method:statevector")["price"]["memory_bytes"] = Value::Null)), + (&[PLANNER_FORM], Box::new(|b| at(b, "method:statevector")["price"]["work"] = Value::Null)), + (&[PLANNER_FORM], Box::new(|b| at(b, "provider:qpu")["price"]["memory_bytes"] = json!(1024))), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["host"]["providers"] = json!(["someone-else"]))), + (&[PLANNER_FORM], Box::new(|b| b["result"]["planner"]["host"]["providers"] = json!([]))), + (&[SHADOW], Box::new(|b| b["result"]["shadow"]["distinct_outcomes"] = json!(7))), + (&[SHADOW], Box::new(|b| { + let shadow = &mut b["result"]["shadow"]; + let n = shadow["counts"]["00"].take(); + let o = shadow["counts"].as_object_mut().unwrap(); + o.shift_remove("00"); + o.insert("ab".into(), n); + })), + ]); +} + +/// What `--recheck` adds to a verifier: which method a shadow ran, or that none +/// could, is what this engine plans; a shadow's class is what it gives; a device +/// target's method is its own; and a route only a sealing host could price does +/// not make an honest receipt look wrong. +#[test] +fn recheck_plans_the_shadow_again_and_leaves_the_host_s_routes_to_the_host() { + let good = provider_body(&device_contract(), vec![quote("qpu", "silicon", usd("0.3"), Some(12.0))], vec![450, 100, 0, 450]); + assert_eq!(recheck(reg(), &good).unwrap()["holds"], true); + let edited = |edit: &dyn Fn(&mut Value)| recheck(reg(), &resealed(&good, edit)).unwrap(); + // No shadow, said to be for want of a method, on a Bell pair. + let skipped = edited(&|b| { + b["result"]["planner"]["shadow"] = json!({ "route": null, "code": "none", "why": "said so" }); + b["result"]["shadow"] = json!({ "ran": false, "code": "none", "why": "said so" }); + }); + assert_eq!((skipped["holds"].as_bool(), skipped["shadow"]["same"].as_bool()), (Some(false), Some(false)), "{skipped}"); + assert!(skipped["shadow"]["why"].as_str().unwrap().contains("method:exact"), "{skipped}"); + // The same, said by another engine: its version is its host's word, so the + // receipt is held neither way, and never said to hold. + let elsewhere = edited(&|b| { + b["result"]["planner"]["shadow"] = json!({ "route": null, "code": "none", "why": "said so" }); + b["result"]["shadow"] = json!({ "ran": false, "code": "none", "why": "said so" }); + b["result"]["engine"]["version"] = json!("0.0.1"); + }); + assert!(elsewhere["holds"].is_null() && elsewhere["shadow"]["same"].is_null(), "{elsewhere}"); + assert!(elsewhere["shadow"]["why"].as_str().unwrap().contains("method:exact"), "{elsewhere}"); + // Any receipt sealed by another engine version is held neither way, a shadow + // that ran here alike as well. + let other = edited(&|b| b["result"]["engine"]["version"] = json!("0.0.1")); + assert!(other["holds"].is_null(), "{other}"); + // Even where this engine's prices or plans differ: what differs is said, and + // the receipt is held neither way. + let elsewhere_differs = edited(&|b| { + b["result"]["engine"]["version"] = json!("0.0.1"); + b["result"]["planner"]["stable"]["digest"] = json!("00".repeat(32)); + }); + assert!(elsewhere_differs["holds"].is_null(), "{elsewhere_differs}"); + // Its job memory read as a number by value, however it is spelled. + let respelled = edited(&|b| b["result"]["planner"]["host"]["job_bytes"] = json!(1073741824.0)); + assert_eq!(respelled["holds"], true, "{respelled}"); + // Under a contract a provider's result of the earlier form is refused. + let earlier = resealed(&good, |b| { + b["result"].as_object_mut().unwrap().remove("counts_source"); + b["result"].as_object_mut().unwrap().remove("execution"); + }); + assert!(reasons(&earlier).contains(&CONTRACT_FORM), "{:?}", reasons(&earlier)); + // A weaker method run where a stronger one reaches the counts. + let weaker = edited(&|b| { + for side in ["/result/planner/shadow", "/result/shadow"] { + let s = b.pointer_mut(side).unwrap(); + s["route"] = json!("method:statevector"); + s["request"]["method"] = json!("statevector"); + } + }); + assert_eq!(weaker["shadow"]["same"], false, "{weaker}"); + // The class it ran at, stated stronger than a run here gives. + let stated = edited(&|b| b["result"]["shadow"]["accuracy"]["class"] = json!("exact")); + assert_eq!(stated["shadow"]["same"], false, "{stated}"); + // A device target's method is the engine's, not the host's word. + let target = seal_local(&json!({ "qasm": BELL, "shots": 50, "target": "synthetic-line-5", "contract": { "deadline_seconds": 60 } })); + assert_eq!(recheck(reg(), &target).unwrap()["priced"]["same"], true); + let other = resealed(&target, |b| b["result"]["planner"]["named"] = json!("method:trajectories")); + assert_eq!(recheck(reg(), &other).unwrap()["priced"]["same"], false); + // An honest receipt whose auto is a route only its host prices: the GPU's, + // where exact and the state vector are past the job's memory. + let sealed_on_a_gpu = seal_local(&json!({ "qasm": BELL, "shots": 100, "contract": { "deadline_seconds": 60 } })); + let gpu = resealed(&sealed_on_a_gpu, |b| { + let price = at(b, "method:exact")["price"].clone(); + let r = at(b, "method:statevector_single"); + r["price"] = price; + r["auto_rank"] = json!(0); + b["result"]["planner"]["auto"] = json!("method:statevector_single"); + }); + assert_eq!(recheck(reg(), &gpu).unwrap()["priced"]["same"], true, "a route this host cannot price is the sealing host's word"); +} + +/// A deadline is reported for every local run: a result that states no time of its +/// own, so that its bits are the same everywhere, has the host's. +#[test] +fn a_target_s_and_a_pulse_program_s_deadline_is_reported_kept() { + let target = seal_local(&json!({ "qasm": BELL, "shots": 50, "target": "synthetic-line-5", "contract": { "deadline_seconds": 60 } })); + assert!(target["result"].get("elapsed_ms").is_none()); + let kept = &target["result"]["planner"]["kept"]["deadline"]; + assert!(kept["elapsed_ms"].is_u64() && kept["kept"] == true, "{kept}"); + assert_eq!(reasons(&target), Vec::<&str>::new()); + // Stated past it, by the host's clock, it says so. + let late = resealed(&target, |b| { + let k = &mut b["result"]["planner"]["kept"]["deadline"]; + k["elapsed_ms"] = json!(61_000); + k["kept"] = json!(false); + }); + assert_eq!(reasons(&late), Vec::<&str>::new()); + assert_eq!(reasons(&resealed(&target, |b| b["result"]["planner"]["kept"]["deadline"]["kept"] = json!(false))), vec![PLANNER_KEPT]); +} diff --git a/wai/wai-quantum/src/engine/provider.rs b/wai/wai-quantum/src/engine/provider.rs index 70d4f856e..a9853ae7b 100644 --- a/wai/wai-quantum/src/engine/provider.rs +++ b/wai/wai-quantum/src/engine/provider.rs @@ -351,7 +351,7 @@ fn hex64(v: &Value) -> bool { /// A provider's provenance as §5.1 has it: `silicon`, or `simulator` or /// `emulator`, alone or followed by `:` and what it is. The class its results /// take: `measured` for silicon, `simulated` for the others. -fn class_of_provenance(p: &str) -> Option<&'static str> { +pub(crate) fn class_of_provenance(p: &str) -> Option<&'static str> { let kind = p.split_once(':').map_or(p, |(k, _)| k); match (kind, p) { (_, "silicon") => Some("measured"), @@ -413,8 +413,15 @@ pub fn check(request: &Value, result: &Value) -> (Vec<&'static str>, Option chosen, + p => p.and_then(Value::as_str), + }; + if result.pointer("/provider/name").and_then(Value::as_str).is_none_or(|n| asked_of != Some(n)) { out.push(REQUEST_PROVIDER); } let default_shots = json!(1024); @@ -547,7 +554,13 @@ pub struct Request { /// is a program that measures in the middle or turns by an angle that is not /// a dyadic multiple of 2π. pub fn read(v: &Value) -> Result { - let provider = v.get("provider").and_then(Value::as_str).filter(|s| !s.is_empty()).ok_or("a provider job names its provider: \"provider\": \"\"")?.to_string(); + read_named(v, None) +} + +/// [`read`], for a job its contract's planner routed to the provider `name`: the +/// job names none itself, and a job that does is read as naming its own. +pub fn read_named(v: &Value, name: Option<&str>) -> Result { + let provider = v.get("provider").and_then(Value::as_str).or(name).filter(|s| !s.is_empty()).ok_or("a provider job names its provider: \"provider\": \"\"")?.to_string(); let src = v.get("qasm").and_then(Value::as_str).ok_or("a job needs \"qasm\": an OpenQASM 3 program")?; if let Some(at) = super::receipt::inexact_number(v) { return Err(format!("`{at}`: a whole number here must be within ±9007199254740991 (2^53 − 1), so that every JSON reader reads it alike and the receipt binds it")); diff --git a/wai/wai-quantum/src/engine/pulse.rs b/wai/wai-quantum/src/engine/pulse.rs index 18c62938f..15e8d0704 100644 --- a/wai/wai-quantum/src/engine/pulse.rs +++ b/wai/wai-quantum/src/engine/pulse.rs @@ -61,7 +61,9 @@ pub const DEFAULT_ANHARMONICITY_MHZ: f64 = -300.0; /// The most samples a schedule's view writes out in full. pub const MAX_VIEW_SAMPLES: usize = 65_536; -const KEYS: [&str; 8] = ["qasm", "method", "shots", "seed", "pulse", "target", "dry_run", "verdict"]; +// `contract` is the planner's to read (engine::planner): a pulse job under one is +// held to it like any other. +const KEYS: [&str; 9] = ["qasm", "method", "shots", "seed", "pulse", "target", "dry_run", "verdict", "contract"]; const OPTIONS: [&str; 7] = ["dt_ns", "levels", "tolerance", "substeps", "qubits", "couplings", "ports"]; const QUBIT_KEYS: [&str; 5] = ["frequency_ghz", "rabi_mhz", "anharmonicity_mhz", "t1_us", "t2_us"]; diff --git a/wai/wai-quantum/src/engine/refusal.rs b/wai/wai-quantum/src/engine/refusal.rs index 6331965ed..ea976b743 100644 --- a/wai/wai-quantum/src/engine/refusal.rs +++ b/wai/wai-quantum/src/engine/refusal.rs @@ -118,6 +118,13 @@ table! { CONTRACT = "J064", Refused, "A registered component's answer that breaks the engine's contract: a method's result without an accuracy class it declared, or one that writes a member the engine writes (method, qubits, gates, compiled, repaired, engine, schema, components, receipt, verdict); a pass's gates on qubits the program does not have, or that do not read back; a front end's program that does not read. Nothing it gave is returned."; REGISTERED_INTENT = "J065", Refused, "An intent on a job whose noise names a registered channel: the intent checks model the built-in channels alone, so the check is refused rather than made against another model."; + // A contract (engine::planner). + CONTRACT_FORM = "J070", Refused, "A contract that does not read: not an object, a member a contract does not have, an exactness that is no class, a max_cost that is not an amount in decimals and a currency, a deadline or an energy ceiling that is not above zero, providers that is neither never nor allowed, or a job that names a provider while its contract does not allow one (providers: never is the default)."; + NOTHING_MEETS = "J071", Refused, "No route this host can see meets the contract: each route's price or reason is listed, so the contract or the job can be changed. Nothing fell back to a route the contract does not allow."; + CLASS_BROKEN = "J072", Refused, "A route's result whose accuracy class does not meet the class its job wants: the contract's, or under a contract that names none the class the job keeps. Nothing it gave is returned, since its receipt would not verify."; + CONTRACT_HERE = "J073", Refused, "A contract where it cannot be honoured: on a set or an item of one (each program runs under its own contract, alone), or on a build with no planner. It is refused rather than read as absent."; + DEADLINE_PASSED = "J074", Refused, "A run stopped at its contract's deadline, by a host that can stop one: the job service's worker, or a provider's job the command line cancels where it waits. The estimate it was planned on was wrong here, and nothing was sealed."; + // An answer's view statements (the answer view layer). ANSWER_PARSE = "J100", Dropped, "A line of an answer that is not a statement (`name = View(...)`), a program (a fenced `qasm` block with its name), a comment or a marker: left out."; ANSWER_VIEW = "J101", Dropped, "A view the answer layer does not have: left out (the views are listed in the layer's specification)."; diff --git a/wai/wai-quantum/src/engine/registry/builtin.rs b/wai/wai-quantum/src/engine/registry/builtin.rs index e960c3a84..f9238f6aa 100644 --- a/wai/wai-quantum/src/engine/registry/builtin.rs +++ b/wai/wai-quantum/src/engine/registry/builtin.rs @@ -66,7 +66,16 @@ const METHODS: [BuiltinMethod; 12] = [ m("trajectories", &["estimate"], true, [Some(30), None, None, None]), ]; -fn question_index(q: Question) -> usize { +/// What the built-in method `name` declares of itself that a verifier reads, +/// from the tables alone ([`super::declared`]). +pub(super) fn declared(name: &str) -> Option { + if name == crate::engine::pulse::METHOD { + return Some(super::Declared { classes: PULSE_CLASSES, ranks: [None; 4] }); + } + METHODS.iter().find(|m| m.name == name).map(|m| super::Declared { classes: m.classes, ranks: m.ranks }) +} + +pub(super) fn question_index(q: Question) -> usize { match q { Question::Noise => 0, Question::Counts => 1, @@ -120,6 +129,9 @@ impl Method for BuiltinMethod { #[derive(Clone, Copy)] struct PulseMethod; +/// The pulse method's one class: its error is bounded by its series' order. +const PULSE_CLASSES: &[&str] = &["bounded"]; + impl Method for PulseMethod { fn name(&self) -> &str { crate::engine::pulse::METHOD @@ -128,7 +140,7 @@ impl Method for PulseMethod { ENGINE_VERSION } fn classes(&self) -> Vec { - vec!["bounded".into()] + PULSE_CLASSES.iter().map(|c| c.to_string()).collect() } fn descriptor(&self) -> Value { let mut d = crate::engine::pulse::describe(); diff --git a/wai/wai-quantum/src/engine/registry/mod.rs b/wai/wai-quantum/src/engine/registry/mod.rs index 9a83c3468..6964753e4 100644 --- a/wai/wai-quantum/src/engine/registry/mod.rs +++ b/wai/wai-quantum/src/engine/registry/mod.rs @@ -201,6 +201,33 @@ impl Question { } } +/// What a built-in method declares of itself that a verifier reads: its +/// accuracy classes and where `auto` tries it, as [`Method::classes`] and +/// [`Method::auto_rank`] give them ([`declared`]). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Declared { + /// Its accuracy classes, in the order [`Method::classes`] gives them. + pub classes: &'static [&'static str], + ranks: [Option; 4], +} + +impl Declared { + /// Where `auto` tries it for `question`, as [`Method::auto_rank`] gives it. + pub fn auto_rank(&self, question: Question) -> Option { + self.ranks[builtin::question_index(question)] + } +} + +/// What the built-in method `name` declares of itself that a verifier reads, +/// or `None` for a name no built-in holds. Read from the built-ins' tables +/// alone: nothing reaches a method's plan or run, so a check that reads this +/// (a contract job's reasoning, [`super::planner::check`]) links none of the +/// methods, and a page that carries the check (the views) carries no +/// simulator. A test holds it to [`Registry::builtins`]. +pub fn declared(name: &str) -> Option { + builtin::declared(name) +} + // --------------------------------------------------------------------------- // The four traits // --------------------------------------------------------------------------- @@ -905,6 +932,11 @@ impl Registry { if let Some(at) = inexact_integer(request) { return Err(tag(refusal::LIMIT, format!("`{at}`: a whole number here must be within ±9007199254740991 (2^53 − 1), so that every JSON reader reads it alike and the receipt binds it"))); } + // A contract's reasoning travels with its result (engine::planner). + #[cfg(feature = "quantum_receipt")] + if super::planner::has_contract(request) { + return super::planner::plan_and_run_in(self, request, &super::planner::Host::new(job_bytes)); + } let plan = self.plan(request, job_bytes)?; let result = self.run(request, &plan)?; Ok((plan, result)) diff --git a/wai/wai-quantum/src/engine/registry/tests.rs b/wai/wai-quantum/src/engine/registry/tests.rs index ff05fbdc1..991236527 100644 --- a/wai/wai-quantum/src/engine/registry/tests.rs +++ b/wai/wai-quantum/src/engine/registry/tests.rs @@ -344,6 +344,29 @@ fn every_built_in_registers_through_its_trait_in_a_fixed_order() { } } +/// What a verifier reads of a built-in without reaching its code is what the +/// built-in says through its trait: every class, in order, and its rank for +/// every question; and nothing is declared of a name no built-in holds, a +/// host's own method's included. +#[test] +fn a_built_in_s_declaration_is_what_its_trait_says() { + let r = Registry::with_builtins(); + let mut seen = 0; + for m in r.methods() { + let d = declared(m.name()).unwrap_or_else(|| panic!("{} is declared", m.name())); + assert_eq!(d.classes.iter().map(|c| c.to_string()).collect::>(), m.classes(), "{}", m.name()); + for q in Question::ALL { + assert_eq!(d.auto_rank(q), m.auto_rank(q), "{} for {q:?}", m.name()); + } + seen += 1; + } + assert_eq!(seen, 13, "every built-in method"); + for name in ["basis_table", "auto", "provider", "", "Exact"] { + assert_eq!(declared(name), None, "{name}"); + } + assert!(host().method("basis_table").is_some() && declared("basis_table").is_none(), "a host's method is not a built-in's declaration"); +} + /// `auto` tries the methods in the order it always has. #[test] fn auto_tries_the_built_ins_in_the_order_it_did() { diff --git a/wai/wai-quantum/src/engine/run.rs b/wai/wai-quantum/src/engine/run.rs index 6415272bc..13257a4bb 100644 --- a/wai/wai-quantum/src/engine/run.rs +++ b/wai/wai-quantum/src/engine/run.rs @@ -174,6 +174,9 @@ pub(crate) fn run_in(reg: &Registry, request: &Value, plan: &Plan) -> Result) -> Result { let mut out = run_job(reg, request, plan, passes)?; + // A contract's class holds, or nothing comes back (engine::planner). + #[cfg(feature = "quantum_receipt")] + crate::engine::planner::hold_class(request, &out)?; // A pulse run carries its own verdict (engine::pulse). if crate::engine::verdict::asked(request) && catalog::reads_own(reg, request).is_none() { out["verdict"] = crate::engine::verdict::of_run_in(reg, request, &out, plan.memory_bytes)?; diff --git a/wai/wai-quantum/src/engine/sets.rs b/wai/wai-quantum/src/engine/sets.rs index 34bb76140..a5275eb87 100644 --- a/wai/wai-quantum/src/engine/sets.rs +++ b/wai/wai-quantum/src/engine/sets.rs @@ -81,6 +81,15 @@ fn shared(request: &Value) -> Map { /// The items `request` gives, in order, or why it is not a set that reads. pub fn expand(request: &Value) -> Result, String> { + let items = expand_items(request)?; + // A contract's reasoning is one job's: a set's items would each drop it. + if items.iter().any(|i| super::planner::has_contract(&i.request)) { + return Err(super::refusal::tag(super::refusal::CONTRACT_HERE, "a contract is one job's: send each program alone under its own, since a set's receipt binds no planner's reasoning")); + } + Ok(items) +} + +fn expand_items(request: &Value) -> Result, String> { let programs = request.get("programs").filter(|v| !v.is_null()); let sweep = request.get("sweep").filter(|v| !v.is_null()); match (programs, sweep) { diff --git a/wai/wai-quantum/src/qasm/lang_tests.rs b/wai/wai-quantum/src/qasm/lang_tests.rs index 086eb153d..76bfc652e 100644 --- a/wai/wai-quantum/src/qasm/lang_tests.rs +++ b/wai/wai-quantum/src/qasm/lang_tests.rs @@ -652,6 +652,18 @@ pub(crate) fn chain(kind: &str, d: usize, k: usize, inner: usize) -> String { /// through calls is bounded as nesting in one body is. #[test] fn nesting_is_bounded_as_the_text_counts_it() { + // Where the bound falls, read on the stack a debug build needs at it: a debug build's + // frames are many times a release build's, and a program at the bound overflows the + // 2 MiB a test thread has. What the bound asks of a stack is tests/reader_stack.rs's, + // which reads at it on 1 MiB in a release build and 16 MiB in a debug one, as here. + // wasm32 has no threads: there it reads inline. + #[cfg(not(target_family = "wasm"))] + std::thread::Builder::new().stack_size(16 << 20).spawn(nesting_bound).expect("a thread for the reading").join().unwrap_or_else(|e| std::panic::resume_unwind(e)); + #[cfg(target_family = "wasm")] + nesting_bound(); +} + +fn nesting_bound() { for shape in ["parens", "unary", "sum", "product", "index", "concat", "type", "blocks", "ifs", "fors"] { let past = read(&nested(shape, 127)).map(|_| ()).unwrap_err(); assert_eq!(past.code, "Q130", "{shape} at 129: {past}"); diff --git a/wai/wai-quantum/src/quantum_cutrank.rs b/wai/wai-quantum/src/quantum_cutrank.rs index b0013f691..31500b8d2 100644 --- a/wai/wai-quantum/src/quantum_cutrank.rs +++ b/wai/wai-quantum/src/quantum_cutrank.rs @@ -93,6 +93,12 @@ pub struct ProductMeasured { steps: Vec, } +/// 2^k exactly, from the double's bits rather than a library's `exp2`, which +/// need not agree in the last place on every platform. +fn pow2(k: usize) -> f64 { + if k > 1023 { f64::INFINITY } else { f64::from_bits(((k as u64) + 1023) << 52) } +} + impl ProductMeasured { /// The state `tableau` holds with `last[q]` applied to each qubit q, to be /// summed in the qubits' own order. @@ -243,7 +249,7 @@ impl ProductMeasured { /// The work of an order: `Σ_k 2^{cut_k}`, the table entries its passes /// touch, up to a small factor. pub fn work(&self) -> f64 { - self.cuts.iter().map(|&k| (k as f64).exp2()).sum() + self.cuts.iter().map(|&k| pow2(k)).sum() } /// An order with less work, by simulated annealing from the current one: @@ -256,7 +262,7 @@ impl ProductMeasured { pub fn anneal_order(&self, moves: usize, seed: u64) -> Vec { let n = self.n; let mut s = seed; - let work = |c: &[usize]| c.iter().map(|&k| (k as f64).exp2()).sum::(); + let work = |c: &[usize]| c.iter().map(|&k| pow2(k)).sum::(); let mut order = self.order.clone(); let mut cuts = self.cuts.clone(); let mut cur = work(&cuts); @@ -284,7 +290,11 @@ impl ProductMeasured { assert_eq!(cand_cuts, self.cut_ranks_of(&cand), "the recounted cuts are the whole order's"); let c = work(&cand_cuts); // The acceptance draw only for a worse order. - if c <= cur || ((cur.log2() - c.log2()) / temp).exp() > (splitmix(&mut s) >> 11) as f64 / (1u64 << 53) as f64 { + // The same bits on every platform (crate::repro): the planner's order, + // and so a plan's memory and work, are part of what a contract job's + // stable digest pins. + let accept = || crate::repro::exp((crate::repro::ln(cur) - crate::repro::ln(c)) / std::f64::consts::LN_2 / temp); + if c <= cur || accept() > (splitmix(&mut s) >> 11) as f64 / (1u64 << 53) as f64 { order = cand; cuts = cand_cuts; cur = c; diff --git a/wai/wai-quantum/src/repro.rs b/wai/wai-quantum/src/repro.rs index 70c3ecc78..6cb6596f8 100644 --- a/wai/wai-quantum/src/repro.rs +++ b/wai/wai-quantum/src/repro.rs @@ -40,28 +40,28 @@ pub use trig::sin_cos; // Natural logarithm // --------------------------------------------------------------------------- -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LN2_HI: f64 = 6.931_471_803_691_238_164_90e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LN2_LO: f64 = 1.908_214_929_270_587_700_02e-10; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG1: f64 = 6.666_666_666_666_735_130e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG2: f64 = 3.999_999_999_940_941_908e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG3: f64 = 2.857_142_874_366_239_149e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG4: f64 = 2.222_219_843_214_978_396e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG5: f64 = 1.818_357_216_161_805_012e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG6: f64 = 1.531_383_769_920_937_332e-1; -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] const LG7: f64 = 1.479_819_860_511_658_591e-1; /// The natural logarithm, within an ulp of the true value: `−∞` at zero, NaN /// below it. -#[cfg(any(feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_vml", feature = "quantum_kernel", feature = "quantum_resource", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_dmrg", feature = "quantum_noisy", feature = "quantum_tableau", feature = "quantum_lang"))] pub fn ln(x: f64) -> f64 { let mut bits = x.to_bits(); let mut hx = (bits >> 32) as u32; @@ -105,7 +105,7 @@ pub fn ln(x: f64) -> f64 { // Exponential // --------------------------------------------------------------------------- -#[cfg(any(feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_nqs", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_cutrank", feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_nqs", feature = "quantum_lang"))] const EXP_P: [f64; 5] = [ 1.666_666_666_666_660_190_37e-1, -2.777_777_777_701_559_338_42e-3, @@ -117,7 +117,7 @@ const EXP_P: [f64; 5] = [ /// `eˣ`, bit-identical on every IEEE-754 platform: fdlibm's algorithm /// (reduction by `ln 2` in two parts, a rational approximation on /// `[−ln2/2, ln2/2]`), using only `+ − × ÷`. Within an ulp of the true value. -#[cfg(any(feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_nqs", feature = "quantum_lang"))] +#[cfg(any(feature = "quantum_frame", feature = "quantum_tn", feature = "quantum_gbs", feature = "quantum_arch", feature = "quantum_qio", feature = "quantum_nqs", feature = "quantum_lang", feature = "quantum_cutrank"))] pub fn exp(x: f64) -> f64 { const LN2_HI_E: f64 = 6.931_471_803_691_238_164_90e-1; const LN2_LO_E: f64 = 1.908_214_929_270_587_700_02e-10; diff --git a/wai/wai-quantum/views/manifest.json b/wai/wai-quantum/views/manifest.json index 970ba68d8..bc2c97c1c 100644 --- a/wai/wai-quantum/views/manifest.json +++ b/wai/wai-quantum/views/manifest.json @@ -4,22 +4,24 @@ "placeholder": "__WAI_QUANTUM_VIEW__", "limit_bytes": 1048576, "bytes": { - "page": 983280, - "script": 95807, + "page": 904051, + "script": 95922, "styles": 50804, - "engine_wasm": 244359, - "engine_wasm_base64": 325812, - "engine_js": 510407 + "engine_wasm": 281266, + "engine_wasm_deflated": 135225, + "engine_wasm_base64": 180300, + "engine_js": 576575 }, "sha256": { - "page": "779aa560416afcc677fc4efb28f2a6ac55ff3e4bb3436f3d381e7197fbaf0ce2", - "script": "6fbf441c1d2f095f0a5f14adaeb10740add48c4122d01a8f15e03b0f59045bde", + "page": "5be4f0480029d1fc9fc3aa96ddf0adfa8860f947ba70540a38834a7e114e8e22", + "script": "292084d11ac2b7bacf0c9314a3f0c11362c9cd2a7d739db0f3ff624819c3c04b", "styles": "11ebcd4416c68e9eaf1156ca6f7c92b9a96744895ed13c377eba98fdd8dca9a6", - "engine_wasm": "980a4a222518c3dcc07bc3e537950c115d1fb02ec8a02757ea646b562e329dd6", - "engine_js": "9733679060ee525e68e941477acd9b077b6155950637648e00b7893ab2814f1a" + "engine_wasm": "fac677fe6c7cf12f068a1189a52f45cf9b3b6ed0f01da7a44056df5429a52738", + "engine_wasm_deflated": "ca5d344c68f0bdbabfd56c60f275701a3ad4ae44f751c7dbf68829f6d1247ac4", + "engine_js": "5abe86e71a5568597d1f759fef2a62ffe4a00fd933b131baa2d71ab8a155d192" }, "sources": { - "wai/quantum-studio/build-views.mjs": "da5b161829a990b3d1bb4c1b3ec7c8f254ff7b5078476156e504ae322bc4f010", + "wai/quantum-studio/build-views.mjs": "ae4aca713fb9a2c2b9228deef292ad5d09eac8185a01bcfd87345b6f067f701f", "wai/quantum-studio/locales/en/assistant.json": "3fca2eca4c2eab7b5c1af71bd2c4e92f48c7102cd786962e343f899d367a2e2c", "wai/quantum-studio/locales/en/circuit_svg.json": "d54b6c26e870f45c40b48497699f81b9203c1c201179b4c0d5e9a300e97203a6", "wai/quantum-studio/locales/en/compile_view.json": "d62e2314eb462c944755c90c93ea10ac4cdf2c22a7781b66b5c3a7829b063d3d", @@ -59,7 +61,7 @@ "wai/quantum-studio/src/studio.css": "8891f2a1b71e1ada344ee1dc41939ba9cd41232f25ab2703d05394c141855997", "wai/quantum-studio/src/tokens.css": "492fbaf8a6cc5b1f7e89346336af3e0a1930a0b48a23731d80d86c128a9032c3", "wai/quantum-studio/src/verdict-view.js": "aec18c93c6f502657ffe2981ca4d9ae0956e1277638d1a9bb1b0846ac8e80160", - "wai/quantum-studio/src/views/check.js": "2edae7b446e72a49293478ebcbfe21792b74762dcfb097fb9e75ec3a4feb8d9a", + "wai/quantum-studio/src/views/check.js": "e3bce09f12039f37b892d51dc51aea277ecc9a38ba4c066717d06f9c49c78f5e", "wai/quantum-studio/src/views/host.js": "2390e14b9e58005f2590fe7d7202a003312f07ffb0ee996469f3f9555c748bee", "wai/quantum-studio/src/views/main.js": "4129c45e35f65caaedb9e2fd4e0e2e1a29ba6ff27b33c5190924c8cc13b2a5cd", "wai/quantum-studio/src/views/render.js": "b3f8bd6717bd18b6275ea8fc94cd2be31f81ef0a8d7c46a882e03085a67eaea4", diff --git a/wai/wai-quantum/views/wai-quantum-views.html b/wai/wai-quantum/views/wai-quantum-views.html index e9b68b163..fd2eefcba 100644 --- a/wai/wai-quantum/views/wai-quantum-views.html +++ b/wai/wai-quantum/views/wai-quantum-views.html @@ -11,10 +11,10 @@
- - diff --git a/wai/wai-rs/src/bin/wai_cli/dx/independent.rs b/wai/wai-rs/src/bin/wai_cli/dx/independent.rs index fe501374b..e11c4958c 100644 --- a/wai/wai-rs/src/bin/wai_cli/dx/independent.rs +++ b/wai/wai-rs/src/bin/wai_cli/dx/independent.rs @@ -80,6 +80,7 @@ include!(concat!(env!("OUT_DIR"), "/independent_verifiers.rs")); /// no line here: its step says where it runs.) pub const NOT_HERE: &[(&str, &str)] = &[ ("pack-conformance/pack_verify.py", "wai-pack.yml runs it, beside the reference packager's differentials against it"), + ("pack-conformance/multi_verify.py", "wai-pack.yml runs it on the packages of several components, recomputing each component from its sources"), ]; /// The entry named `name`. diff --git a/wai/wai-rs/src/codecs/registry.rs b/wai/wai-rs/src/codecs/registry.rs index e285f9c5d..65902ff06 100644 --- a/wai/wai-rs/src/codecs/registry.rs +++ b/wai/wai-rs/src/codecs/registry.rs @@ -1157,6 +1157,7 @@ pub const UNREGISTERED_LABELS: &[UnregisteredLabel] = &[ label("wai.quantum.docs-manifest/1", "a document with no schema file: the list of documents tools/quantum-docs checks"), label("wai.quantum.write/1", "a document with no schema file: the transcript wai-quantum-writer keeps of writing a program for a task"), label("wai.quantum.model/1", "a document with no schema file: the manifest of a writer's model, the file wai-model.json (wai-quantum-writer's `coder`)"), + label("wai.quantum.timings/1", "a document with no schema file: the runs the command line has timed and read the energy of on this machine, by method, that its estimate of a job's energy rests on (wai-quantum-cli's `estimates`)"), // The domains a digest starts with. label("wai.quantum.job-key/1", "a digest domain: the digest a job service keeps a client's idempotency key under, the client's name beside the key (wai-quantum-service)"), label("wai.quantum.trace/1", "a digest domain: an optimisation trace's first link is BLAKE3 of it and the request's canonical text (wai-quantum's `engine::variational`)"), @@ -1165,6 +1166,8 @@ pub const UNREGISTERED_LABELS: &[UnregisteredLabel] = &[ label("wai.quantum.other", "refused on purpose: not a kernel; the fabric's test puts it in a certificate to see the placement refuse that certificate"), label("wai.quantum.x/one", "refused on purpose: not a schema's name, its major not a number; the schema module's test gives it to see no file named for it"), label("wai.quantum.job-result/2", "refused on purpose: a major of the job result's schema that no text defines; a test writes it into a sealed result to see the receipt fail"), + label("wai.quantum.planner/2", "refused on purpose: a format of a contract job's reasoning that no text defines; the planner's test and the job receipts corpus seal it in a result to see the reasoning refused (quantum-providers §8.7)"), + label("wai.quantum.timings/9", "refused on purpose: a major of the command line's timings that no text defines; its test writes it to see the file kept aside and a new one begun"), label("wai.quantum.target/2", "refused on purpose: a major of the device target's schema that no text defines; the targets' test gives it to see the document refused"), label("wai.quantum.provider/2", "refused on purpose: a version of the provider protocol that no text defines; the reference provider's test sends it to see it answered unsupported_version (quantum-providers §10)"), label("wai.quantum.provider/9", "refused on purpose: a version of the provider protocol that no text defines; the protocol schema's test sends it to see it answered unsupported_version (quantum-providers §10)"),