diff --git a/TASK_DETAILS.md b/TASK_DETAILS.md
index b331f7d8..fe28b69e 100644
--- a/TASK_DETAILS.md
+++ b/TASK_DETAILS.md
@@ -56,7 +56,7 @@ We welcome new engineering problem ideas — even without complete verification
Cross-modality gene expression prediction (RNA → ADT), NeurIPS 2021 |
- | QuantumComputing |
+ QuantumComputing |
routing_qftentangled |
QFT circuit routing optimization on IBM Falcon (gate count & depth) |
@@ -68,6 +68,10 @@ We welcome new engineering problem ideas — even without complete verification
cross_target_qaoa |
Cross-target robust QAOA optimization for IBM and IonQ backends |
+
+ KernelBlockEncoding |
+ Normalization-aware FABLE circuit construction for QML kernel matrices under independent resource and block-error evaluation |
+
| Cryptographic |
AES-128 CTR |
diff --git a/TASK_DETAILS_zh-CN.md b/TASK_DETAILS_zh-CN.md
index 44d1b1fa..8b6d1e35 100644
--- a/TASK_DETAILS_zh-CN.md
+++ b/TASK_DETAILS_zh-CN.md
@@ -56,7 +56,7 @@ Frontier-Eng 目前已覆盖以下领域的任务。每个任务均配有可运
跨模态基因表达预测(RNA → ADT),NeurIPS 2021 |
- | QuantumComputing |
+ QuantumComputing |
routing_qftentangled |
QFT 线路路由优化,IBM Falcon(gate count & depth) |
@@ -68,6 +68,10 @@ Frontier-Eng 目前已覆盖以下领域的任务。每个任务均配有可运
cross_target_qaoa |
跨目标鲁棒 QAOA 优化(IBM & IonQ) |
+
+ KernelBlockEncoding |
+ 在独立资源与分块误差评测下,为 QML 核矩阵构造归一化感知的 FABLE 电路 |
+
| Cryptographic |
AES-128 CTR |
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/README.md b/benchmarks/QuantumComputing/KernelBlockEncoding/README.md
new file mode 100644
index 00000000..fd3c2190
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/README.md
@@ -0,0 +1,68 @@
+# Kernel Block Encoding
+
+This benchmark asks a C++ policy to construct compressed FABLE-style quantum
+circuits for fixed-point kernel and Gram matrices used in machine learning. A
+candidate chooses a partial-Hadamard basis, normalization, and sparse quantized
+rotation vector. The independent evaluator analytically reconstructs the encoded
+matrix, enforces the approximation budget, and applies a frozen gate compiler and
+resource objective.
+
+This is a circuit-construction task, not QML training or state-vector simulation.
+The candidate directly changes the block encoding that is measured.
+
+## Files
+
+- `Task.md`: mathematical contract, C++ API, resource model, workloads, and score.
+- `references/problem_config.json`: frozen kernels, limits, and objective weights.
+- `references/README.md`: research and construction references.
+- `scripts/init.cpp`: editable C++17 starter policy.
+- `verification/construction_runtime.hpp`: immutable candidate-side construction API.
+- `verification/evaluator.py`: independent workload generator, certificate checker,
+ analytic block reconstruction, frozen resource compiler, and scorer.
+- `verification/limited_exec.py`: thread-safe POSIX hard-limit launcher for candidate
+ processes.
+- `baseline/solution.cpp`: frozen starter used for score normalization.
+- `baseline/result_log.txt`: measured reference evaluation.
+- `frontier_eval/`: unified-task metadata and evaluator wrapper.
+
+## Requirements
+
+- Linux or another POSIX environment with Python 3.10+;
+- `g++` with C++17 support; and
+- one CPU core with less than 1 GiB RAM.
+
+There are no Python packages, downloads, containers, external solvers, GPUs,
+Qiskit, or quantum simulators.
+
+The complete frozen-starter evaluation takes about 2.8 seconds on the repository's
+current AMD EPYC host, including two C++ compilations and twelve construction runs.
+
+## Direct evaluation
+
+From this task directory:
+
+```bash
+python verification/evaluator.py scripts/init.cpp \
+ --metrics-out metrics.json --artifacts-out artifacts.json
+```
+
+The unmodified starter reports `valid=1.0` and `combined_score=1.0`. A score above
+1.0 is an improvement over the frozen starter.
+
+## Unified evaluation
+
+From the repository root:
+
+```bash
+.venvs/frontier-eval-driver/bin/python -m frontier_eval \
+ task=unified \
+ task.benchmark=QuantumComputing/KernelBlockEncoding \
+ algorithm=openevolve \
+ algorithm.iterations=0
+```
+
+## Editing contract
+
+Only change code between `EVOLVE-BLOCK-START` and `EVOLVE-BLOCK-END` in
+`scripts/init.cpp`. The evaluator byte-compares the immutable source prefix and
+suffix against the frozen baseline before compiling a candidate.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/Task.md b/benchmarks/QuantumComputing/KernelBlockEncoding/Task.md
new file mode 100644
index 00000000..8f46eb57
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/Task.md
@@ -0,0 +1,214 @@
+# Task: Kernel Block Encoding
+
+## 1. Engineering problem
+
+Many quantum linear-algebra and quantum machine-learning algorithms assume access
+to a unitary whose leading block is a scaled approximation of a classical matrix.
+General constructions exist, but the actual circuit can be dominated by data
+loading, normalization, controlled rotations, and routing. Kernel matrices make
+the issue concrete: they are dense, but their geometry can create exploitable
+structure in a suitable basis.
+
+This task exposes construction co-design directly. Given a real symmetric kernel
+matrix, choose:
+
+- a computational or partial-Hadamard basis;
+- the block-encoding normalization;
+- which uniformly controlled rotations to retain; and
+- the value of every retained, quantized rotation.
+
+The output is a concrete compressed FABLE construction. The evaluator does not run
+a QML model and does not estimate quality from a state-vector sample. It
+reconstructs the encoded block from the construction integers and computes the
+resources of the corresponding frozen gate schedule.
+
+## 2. Block-encoding family
+
+Let `N = 2^n` and let `A` be an `N x N` fixed-point input matrix. A candidate first
+selects an `n`-bit `basis_mask`. If bit `k` is set, a normalized Hadamard is applied
+to qubit `k` on both sides of the matrix:
+
+```text
+B = H_mask A H_mask
+```
+
+The evaluator implements this transform with integer butterflies. Applying a
+Hadamard on both matrix axes contributes an exact denominator of two, so no
+floating-point matrix transform is needed.
+
+The candidate then selects `s >= max_ij |B_ij|`. Define
+
+```text
+C_ij = B_ij / s
+theta_ij = 2 arccos(C_ij)
+```
+
+Flatten `theta` in row-major order. With `W` the unnormalized Walsh-Hadamard matrix
+of order `N^2` and `P_G` the binary-reflected Gray permutation, the uniformly
+controlled rotation coefficients are
+
+```text
+hat_theta = P_G (W / N^2) theta.
+```
+
+Every emitted coefficient is an integer number of
+`pi / 268435456` radians. Omitted coefficients are exactly zero. The checker
+inverts the Gray permutation and Walsh-Hadamard transform and obtains
+
+```text
+B_tilde_ij = s cos(theta_tilde_ij / 2).
+```
+
+The FABLE oracle, diffusion layers, row/system swap, and optional basis wrappers
+therefore form a unitary `U` on `2n + 1` qubits whose leading block is
+`A_tilde / (N s)`. Its normalization is
+
+```text
+alpha = N s.
+```
+
+The construction uses `n + 1` block-encoding ancillas and `n` system qubits.
+
+## 3. Validity condition
+
+For the system-register leading block of `U`, every workload requires
+
+```text
+|| A - alpha (<0^(n+1)| tensor I) U (|0^(n+1)> tensor I) ||_F <= epsilon.
+```
+
+The evaluator reconstructs the left-hand matrix directly. Since the spectral norm
+is no greater than the Frobenius norm, every accepted construction also has
+spectral block error at most `epsilon`.
+
+Targets, basis transforms, scale bounds, Gray permutations, and quantized angle
+transforms are independently recomputed in Python. Candidate-reported errors and
+resource counts are ignored. A small explicit floating-point guard is added to the
+computed trigonometric error before the validity comparison.
+
+## 4. Candidate API
+
+Only this function is editable:
+
+```cpp
+void optimize(kernel_block_encoding::Construction& construction);
+```
+
+The immutable class in `verification/construction_runtime.hpp` provides:
+
+```cpp
+std::size_t dimension() const;
+std::size_t system_qubits() const;
+std::size_t coefficient_count() const;
+long double epsilon() const;
+long double target(std::size_t row, std::size_t column) const;
+
+void set_basis_mask(std::uint32_t mask);
+std::int64_t minimum_scale_numerator() const;
+void set_scale_numerator(std::int64_t numerator);
+void set_scale_multiplier(long double multiplier);
+
+std::vector exact_angle_ticks() const;
+long double frobenius_error(const std::vector& ticks) const;
+ResourceEstimate resources(const std::vector& ticks) const;
+long double objective(const std::vector& ticks) const;
+void commit(std::vector ticks);
+```
+
+Changing the basis resets the minimum scale. The scale numerator may range from the
+new minimum through 16 times that minimum. `exact_angle_ticks()` produces the full
+quantized FABLE vector for the current basis and scale; a policy may drop or alter
+any tick before committing it. Helper error and resource methods support search,
+but only the independent Python reconstruction determines the score.
+
+## 5. Frozen circuit resources
+
+The sparse coefficient vector is compiled with the compressed uniform-rotation
+schedule:
+
+1. traverse control states in binary-reflected Gray order;
+2. emit one `RY` for each nonzero coefficient;
+3. across a run of zero rotations, cancel repeated control toggles and emit one
+ CNOT for each bit with odd transition parity;
+4. close the Gray cycle;
+5. add the two `n`-Hadamard diffusion layers and `n` register swaps; and
+6. add two Hadamards for every selected basis qubit.
+
+The reported counts are:
+
+- arbitrary-angle `RY` rotations;
+- oracle and total CNOTs, with each SWAP decomposed into three CNOTs;
+- Hadamards;
+- logical depth of the frozen schedule; and
+- `2n + 1` logical qubits.
+
+All oracle rotations and CNOTs touch the rotation target, so they are sequential in
+this construction. The register swaps are disjoint and contribute three depth
+layers.
+
+## 6. Workloads
+
+The evaluator deterministically generates six fixed-point matrices:
+
+1. a 16-sample clustered anisotropic RBF kernel;
+2. a 32-sample, higher-dimensional clustered RBF kernel;
+3. a 32-sample degree-three polynomial Gram matrix;
+4. a 32-sample rational-quadratic kernel;
+5. a 32-node random-walk feature Gram matrix; and
+6. a 64-sample mixture of two RBF length scales.
+
+The RBF generators use high-precision decimal exponentiation before fixed-point
+rounding. Polynomial, rational, and walk kernels use integer arithmetic. Input
+bytes and SHA-256 digests are frozen in `references/problem_config.json` and
+reported in `artifacts.json`.
+
+## 7. Objective
+
+For a valid construction, the frozen compiled cost is
+
+```text
+16 * RY + 1 * CNOT + 0.25 * H + 0.25 * depth.
+```
+
+The scenario objective is
+
+```text
+effective_cost = alpha * compiled_cost.
+```
+
+Multiplying by `alpha` makes normalization part of the optimization: a basis that
+compresses strongly can still lose if its transformed maximum entry is large.
+
+For scenario `i`:
+
+```text
+score_i = baseline_effective_cost_i / candidate_effective_cost_i.
+```
+
+`combined_score` is the geometric mean across all six scenarios. The direct-basis,
+global-threshold starter is frozen as the baseline and scores exactly 1.0. Larger
+is better.
+
+The evaluator isolates workload failures and continues through the full suite. A
+failed workload retains its baseline data and a workload-level error, while every
+successful workload retains its independently checked score. `partial_combined_score`
+is the geometric mean over those successful workloads and is diagnostic only. The
+official `combined_score` remains zero and `valid=0.0` unless all six workloads
+succeed, so skipping a difficult scenario can never improve the optimization
+target.
+
+## 8. Limits and reproducibility
+
+- matrix dimensions are at most 64;
+- scale is at most 16 times the basis-dependent minimum;
+- angle certificates are at most 256 KiB;
+- candidate source is at most 1 MB;
+- candidate execution is limited to 5 seconds and 1 GiB per workload;
+- candidate processes are subject to `RLIMIT_NPROC=64` where supported; and
+- compilation uses `g++ -std=c++17 -O2`.
+
+There is no network access, external solver, quantum SDK, simulator, container,
+GPU, or downloaded data. Compilation is outside candidate execution time but is
+included in evaluator wall time. Invalid source edits, malformed certificates,
+timeouts, scale violations, or excessive block error produce `valid=0.0` and score
+0.0.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/baseline/result_log.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/baseline/result_log.txt
new file mode 100644
index 00000000..af45d6a4
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/baseline/result_log.txt
@@ -0,0 +1,35 @@
+KernelBlockEncoding frozen starter reference
+============================================
+
+Command:
+ python verification/evaluator.py scripts/init.cpp \
+ --metrics-out metrics.json --artifacts-out artifacts.json
+
+Environment:
+ Linux 5.15 x86_64
+ Python 3.10.12
+ g++ 11.4.0
+ AMD EPYC 7313 host
+
+Summary:
+ valid=1.0
+ combined_score=1.0
+ partial_combined_score=1.0
+ scenario_count=6
+ successful_scenario_count=6
+ failed_scenario_count=0
+ checked_matrix_entries=8448
+ total_rotations=6936
+ total_cnots=7788
+ evaluator_wall_s=2.748
+
+Per workload (epsilon, error upper bound, alpha, RY, oracle CNOT, objective):
+ clustered_rbf_16 0.1055240631 0.0433050655 16 236 256 66724
+ anisotropic_rbf_32 0.0925254822 0.0662628832 32 896 1016 507160
+ polynomial_gram_32 0.0619373322 0.0455802581 32 946 1020 533320
+ rational_quadratic_32 0.1412220001 0.1033587668 32 930 1018 524920
+ walk_feature_gram_32 0.1810274124 0.0784774292 32 144 292 87160
+ multiscale_rbf_64 0.1095294952 0.0768379219 64 3784 4096 4264464
+
+Times are descriptive rather than scored. The score uses only independently
+reconstructed block error, normalization, and frozen logical circuit resources.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/baseline/solution.cpp b/benchmarks/QuantumComputing/KernelBlockEncoding/baseline/solution.cpp
new file mode 100644
index 00000000..968bc41b
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/baseline/solution.cpp
@@ -0,0 +1,83 @@
+// Kernel block-encoding construction policy.
+// The evaluator permits edits only inside the marked region.
+
+#include "construction_runtime.hpp"
+
+namespace kernel_block_encoding {
+
+// EVOLVE-BLOCK-START
+void optimize(Construction &construction) {
+ // Valid starter: direct-basis FABLE with a single global pruning threshold.
+ // Better policies can search partial-Hadamard bases and normalization scales,
+ // allocate the error budget per coefficient, and alter retained angles.
+ construction.set_basis_mask(0);
+ construction.set_scale_numerator(construction.minimum_scale_numerator());
+
+ const std::vector exact = construction.exact_angle_ticks();
+ std::vector magnitudes;
+ magnitudes.reserve(exact.size());
+ for (const std::int64_t tick : exact) {
+ if (tick != 0)
+ magnitudes.push_back(std::llabs(tick));
+ }
+ std::sort(magnitudes.begin(), magnitudes.end());
+ magnitudes.erase(std::unique(magnitudes.begin(), magnitudes.end()),
+ magnitudes.end());
+
+ std::vector best = exact;
+ const long double error_budget = 0.75L * construction.epsilon();
+ std::ptrdiff_t low = 0;
+ std::ptrdiff_t high = static_cast(magnitudes.size()) - 1;
+ while (low <= high) {
+ const std::ptrdiff_t middle = low + (high - low) / 2;
+ const std::int64_t threshold = magnitudes[static_cast(middle)];
+ std::vector trial = exact;
+ for (std::int64_t &tick : trial) {
+ if (std::llabs(tick) <= threshold)
+ tick = 0;
+ }
+ if (construction.frobenius_error(trial) <= error_budget) {
+ best = std::move(trial);
+ low = middle + 1;
+ } else {
+ high = middle - 1;
+ }
+ }
+ construction.commit(std::move(best));
+}
+// EVOLVE-BLOCK-END
+
+} // namespace kernel_block_encoding
+
+int main(int argc, char **argv) {
+ std::string input_path;
+ std::string certificate_path;
+ for (int index = 1; index < argc; ++index) {
+ const std::string argument = argv[index];
+ if (argument == "--input" && index + 1 < argc) {
+ input_path = argv[++index];
+ } else if (argument == "--certificate" && index + 1 < argc) {
+ certificate_path = argv[++index];
+ } else {
+ std::cerr << "unknown or incomplete argument: " << argument << '\n';
+ return 2;
+ }
+ }
+ if (input_path.empty() || certificate_path.empty()) {
+ std::cerr
+ << "usage: candidate --input kernel.kbe --certificate circuit.kbc\n";
+ return 2;
+ }
+ try {
+ kernel_block_encoding::Construction construction(input_path,
+ certificate_path);
+ kernel_block_encoding::optimize(construction);
+ construction.write_certificate();
+ std::cout << "workload=" << construction.workload_id()
+ << " dimension=" << construction.dimension() << '\n';
+ return 0;
+ } catch (const std::exception &exception) {
+ std::cerr << "candidate failure: " << exception.what() << '\n';
+ return 1;
+ }
+}
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/agent_files.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/agent_files.txt
new file mode 100644
index 00000000..6eeba3d6
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/agent_files.txt
@@ -0,0 +1,10 @@
+README.md
+Task.md
+scripts/init.cpp
+verification/construction_runtime.hpp
+references/problem_config.json
+references/README.md
+verification/evaluator.py
+verification/limited_exec.py
+verification/test_evaluator.py
+frontier_eval/constraints.txt
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/artifact_files.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/artifact_files.txt
new file mode 100644
index 00000000..d02f2a18
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/artifact_files.txt
@@ -0,0 +1 @@
+# metrics.json and artifacts.json are collected by UnifiedTask directly.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/candidate_destination.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/candidate_destination.txt
new file mode 100644
index 00000000..d26dd4fb
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/candidate_destination.txt
@@ -0,0 +1 @@
+scripts/init.cpp
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/constraints.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/constraints.txt
new file mode 100644
index 00000000..3c7b7808
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/constraints.txt
@@ -0,0 +1,14 @@
+KernelBlockEncoding constraints:
+1) Only modify code between the EVOLVE-BLOCK markers in `scripts/init.cpp`.
+2) Preserve `optimize(kernel_block_encoding::Construction&)` and the immutable C++ shell.
+3) Commit one sparse FABLE angle vector through the provided runtime. The independent
+ evaluator reconstructs the encoded matrix and ignores candidate-reported metrics.
+4) Every scenario must meet its Frobenius block-error budget. This also guarantees
+ that spectral block error is no larger than the same public epsilon.
+5) Optimize normalization-weighted compiled cost across all kernel families. Basis
+ compression can lose if it increases alpha; local angle magnitude is not the
+ same as global matrix-error sensitivity.
+6) Do not modify documentation, baseline, references, verification, or
+ `frontier_eval` metadata. These paths are checked read-only.
+7) Use only the fixed C++17 standard-library environment. No downloads, network,
+ external solvers, quantum SDKs, simulators, containers, or GPUs are available.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/copy_files.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/copy_files.txt
new file mode 100644
index 00000000..9c558e35
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/copy_files.txt
@@ -0,0 +1 @@
+.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/eval_command.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/eval_command.txt
new file mode 100644
index 00000000..c8c51ef9
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/eval_command.txt
@@ -0,0 +1 @@
+bash frontier_eval/run_eval.sh {python} {candidate} metrics.json artifacts.json
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/eval_cwd.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/eval_cwd.txt
new file mode 100644
index 00000000..9c558e35
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/eval_cwd.txt
@@ -0,0 +1 @@
+.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/initial_program.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/initial_program.txt
new file mode 100644
index 00000000..d26dd4fb
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/initial_program.txt
@@ -0,0 +1 @@
+scripts/init.cpp
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/readonly_files.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/readonly_files.txt
new file mode 100644
index 00000000..45915938
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/readonly_files.txt
@@ -0,0 +1,7 @@
+README.md
+Task.md
+baseline
+references
+verification
+frontier_eval
+frontier_eval/run_eval.sh
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/run_eval.sh b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/run_eval.sh
new file mode 100755
index 00000000..f49aa26b
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/frontier_eval/run_eval.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+if [[ $# -ne 4 ]]; then
+ echo "usage: run_eval.sh PYTHON CANDIDATE METRICS_JSON ARTIFACTS_JSON" >&2
+ exit 2
+fi
+
+python_path=$1
+candidate_path=$2
+metrics_path=$3
+artifacts_path=$4
+
+exec "$python_path" verification/evaluator.py "$candidate_path" \
+ --metrics-out "$metrics_path" \
+ --artifacts-out "$artifacts_path"
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/references/README.md b/benchmarks/QuantumComputing/KernelBlockEncoding/references/README.md
new file mode 100644
index 00000000..20807904
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/references/README.md
@@ -0,0 +1,40 @@
+# References and scope
+
+This benchmark implements an original, dependency-free evaluator around the
+published FABLE construction. It does not vendor the authors' Qiskit or MATLAB
+implementations.
+
+## Block encodings and QML
+
+- Gilyén, Su, Low, and Wiebe,
+ [*Quantum singular value transformation and beyond*](https://arxiv.org/abs/1806.01838),
+ define the block-encoding/QSVT framework and include quantum machine-learning
+ applications.
+- Nguyen, Kiani, and Lloyd,
+ [*Block-encoding dense and full-rank kernels using hierarchical matrices*](https://arxiv.org/abs/2201.11329),
+ explain why generic efficient access is a strong assumption for dense kernel
+ matrices and study structure-aware alternatives.
+
+## Circuit constructions
+
+- Camps and Van Beeumen,
+ [*FABLE: Fast Approximate Quantum Circuits for Block-Encodings*](https://arxiv.org/abs/2205.00081),
+ give the Walsh-Hadamard/Gray-code uniformly controlled rotation construction and
+ its compression rule. The authors' reference repository is
+ [QuantumComputingLab/fable](https://github.com/QuantumComputingLab/fable).
+- Kuklinski and Rempfer,
+ [*S-FABLE and LS-FABLE*](https://arxiv.org/abs/2401.04234), introduce Hadamard
+ conjugation as a way to expose compressible structure. This benchmark generalizes
+ that discrete choice to any subset of system qubits.
+- Clader et al.,
+ [*Quantum Resources Required to Block-Encode a Matrix of Classical Data*](https://arxiv.org/abs/2206.03505),
+ demonstrate why circuit count/depth and data-loading resources must be made
+ explicit rather than hidden behind a matrix oracle.
+
+## Benchmark boundary
+
+The score is a logical construction cost, not a claim about one physical quantum
+processor. The frozen weights make normalization, arbitrary rotations, CNOTs, and
+depth jointly visible and reproducible. Fault-tolerant synthesis, hardware routing,
+noise, and alternative block-encoding families are useful future extensions but
+are deliberately outside this first task.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/references/problem_config.json b/benchmarks/QuantumComputing/KernelBlockEncoding/references/problem_config.json
new file mode 100644
index 00000000..d97f7138
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/references/problem_config.json
@@ -0,0 +1,99 @@
+{
+ "benchmark_id": "kernel_block_encoding",
+ "matrix_scale": 1048576,
+ "angle_denominator": 268435456,
+ "objective": {
+ "rotation_weight": 16.0,
+ "cnot_weight": 1.0,
+ "hadamard_weight": 0.25,
+ "depth_weight": 0.25,
+ "normalization_exponent": 1.0
+ },
+ "limits": {
+ "max_candidate_bytes": 1000000,
+ "max_certificate_bytes": 262144,
+ "max_dimension": 64,
+ "max_processes": 64,
+ "max_scale_multiplier": 16,
+ "candidate_timeout_s_per_workload": 5.0,
+ "compile_timeout_s": 30.0,
+ "memory_limit_mb": 1024
+ },
+ "workloads": [
+ {
+ "id": "clustered_rbf_16",
+ "kind": "rbf",
+ "dimension": 16,
+ "feature_dimensions": 3,
+ "clusters": 4,
+ "cluster_separation": 11,
+ "jitter": 3,
+ "bandwidth_squared": 38,
+ "seed": 1229782938247303441,
+ "relative_error_ppm": 18000,
+ "expected_sha256": "7de83c53135924eb3967f0ee622b9fdb9f55cc19bae3f6b4ceee1d6938b1f39e"
+ },
+ {
+ "id": "anisotropic_rbf_32",
+ "kind": "rbf",
+ "dimension": 32,
+ "feature_dimensions": 5,
+ "clusters": 8,
+ "cluster_separation": 9,
+ "jitter": 4,
+ "bandwidth_squared": 52,
+ "seed": 2459565876494606882,
+ "relative_error_ppm": 15000,
+ "expected_sha256": "0a1d779961b02ffbb39ad8a99fa0456c108711af0fd5467cea84ac24ebcaaa84"
+ },
+ {
+ "id": "polynomial_gram_32",
+ "kind": "polynomial",
+ "dimension": 32,
+ "feature_dimensions": 7,
+ "feature_bound": 5,
+ "bias": 96,
+ "degree": 3,
+ "seed": 3689348814741910323,
+ "relative_error_ppm": 12000,
+ "expected_sha256": "dc9a5b6390679ba3fad120bb89e6cd5bde89e75f933c9623be7716204b4f5374"
+ },
+ {
+ "id": "rational_quadratic_32",
+ "kind": "rational_quadratic",
+ "dimension": 32,
+ "feature_dimensions": 4,
+ "feature_bound": 16,
+ "length_squared": 75,
+ "seed": 4919131752989213764,
+ "relative_error_ppm": 14000,
+ "expected_sha256": "b043f769c9cc82076cadeaac67e08e1237418b82bcb5abf619ff43f86b4ddbd5"
+ },
+ {
+ "id": "walk_feature_gram_32",
+ "kind": "walk_gram",
+ "dimension": 32,
+ "shortcut_stride": 7,
+ "walk_steps": 4,
+ "self_weight": 2,
+ "relative_error_ppm": 10000,
+ "expected_sha256": "a04110306f423eb5d12c1ced0c38cfe8dddfba88f7b596540f4c39faa63440f0"
+ },
+ {
+ "id": "multiscale_rbf_64",
+ "kind": "multiscale_rbf",
+ "dimension": 64,
+ "feature_dimensions": 4,
+ "clusters": 8,
+ "cluster_separation": 13,
+ "jitter": 4,
+ "bandwidth_squared_small": 36,
+ "bandwidth_squared_large": 180,
+ "small_weight_numerator": 3,
+ "weight_denominator": 5,
+ "seed": 6148914691236517205,
+ "relative_error_ppm": 9000,
+ "expected_sha256": "5bb408adb4839e8817d11397fa014fff09d6f93407396439664640445b4ddd2c"
+ }
+ ]
+}
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/scripts/init.cpp b/benchmarks/QuantumComputing/KernelBlockEncoding/scripts/init.cpp
new file mode 100644
index 00000000..968bc41b
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/scripts/init.cpp
@@ -0,0 +1,83 @@
+// Kernel block-encoding construction policy.
+// The evaluator permits edits only inside the marked region.
+
+#include "construction_runtime.hpp"
+
+namespace kernel_block_encoding {
+
+// EVOLVE-BLOCK-START
+void optimize(Construction &construction) {
+ // Valid starter: direct-basis FABLE with a single global pruning threshold.
+ // Better policies can search partial-Hadamard bases and normalization scales,
+ // allocate the error budget per coefficient, and alter retained angles.
+ construction.set_basis_mask(0);
+ construction.set_scale_numerator(construction.minimum_scale_numerator());
+
+ const std::vector exact = construction.exact_angle_ticks();
+ std::vector magnitudes;
+ magnitudes.reserve(exact.size());
+ for (const std::int64_t tick : exact) {
+ if (tick != 0)
+ magnitudes.push_back(std::llabs(tick));
+ }
+ std::sort(magnitudes.begin(), magnitudes.end());
+ magnitudes.erase(std::unique(magnitudes.begin(), magnitudes.end()),
+ magnitudes.end());
+
+ std::vector best = exact;
+ const long double error_budget = 0.75L * construction.epsilon();
+ std::ptrdiff_t low = 0;
+ std::ptrdiff_t high = static_cast(magnitudes.size()) - 1;
+ while (low <= high) {
+ const std::ptrdiff_t middle = low + (high - low) / 2;
+ const std::int64_t threshold = magnitudes[static_cast(middle)];
+ std::vector trial = exact;
+ for (std::int64_t &tick : trial) {
+ if (std::llabs(tick) <= threshold)
+ tick = 0;
+ }
+ if (construction.frobenius_error(trial) <= error_budget) {
+ best = std::move(trial);
+ low = middle + 1;
+ } else {
+ high = middle - 1;
+ }
+ }
+ construction.commit(std::move(best));
+}
+// EVOLVE-BLOCK-END
+
+} // namespace kernel_block_encoding
+
+int main(int argc, char **argv) {
+ std::string input_path;
+ std::string certificate_path;
+ for (int index = 1; index < argc; ++index) {
+ const std::string argument = argv[index];
+ if (argument == "--input" && index + 1 < argc) {
+ input_path = argv[++index];
+ } else if (argument == "--certificate" && index + 1 < argc) {
+ certificate_path = argv[++index];
+ } else {
+ std::cerr << "unknown or incomplete argument: " << argument << '\n';
+ return 2;
+ }
+ }
+ if (input_path.empty() || certificate_path.empty()) {
+ std::cerr
+ << "usage: candidate --input kernel.kbe --certificate circuit.kbc\n";
+ return 2;
+ }
+ try {
+ kernel_block_encoding::Construction construction(input_path,
+ certificate_path);
+ kernel_block_encoding::optimize(construction);
+ construction.write_certificate();
+ std::cout << "workload=" << construction.workload_id()
+ << " dimension=" << construction.dimension() << '\n';
+ return 0;
+ } catch (const std::exception &exception) {
+ std::cerr << "candidate failure: " << exception.what() << '\n';
+ return 1;
+ }
+}
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/verification/construction_runtime.hpp b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/construction_runtime.hpp
new file mode 100644
index 00000000..93192ee3
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/construction_runtime.hpp
@@ -0,0 +1,499 @@
+#ifndef KERNEL_BLOCK_ENCODING_CONSTRUCTION_RUNTIME_HPP
+#define KERNEL_BLOCK_ENCODING_CONSTRUCTION_RUNTIME_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace kernel_block_encoding {
+
+inline constexpr std::int64_t kAngleDenominator = std::int64_t{1} << 28;
+inline constexpr std::int64_t kMaximumAngleTicks = 4 * kAngleDenominator;
+inline constexpr std::int64_t kMaximumScaleMultiplier = 16;
+inline constexpr long double kRotationWeight = 16.0L;
+inline constexpr long double kCnotWeight = 1.0L;
+inline constexpr long double kHadamardWeight = 0.25L;
+inline constexpr long double kDepthWeight = 0.25L;
+
+struct InputData {
+ std::string workload_id;
+ std::size_t dimension = 0;
+ std::int64_t matrix_scale = 0;
+ std::int64_t epsilon_numerator = 0;
+ std::vector matrix;
+};
+
+inline bool is_power_of_two(std::size_t value) {
+ return value >= 2 && (value & (value - 1)) == 0;
+}
+
+inline std::size_t integer_log2(std::size_t value) {
+ if (!is_power_of_two(value)) {
+ throw std::runtime_error("dimension is not a supported power of two");
+ }
+ std::size_t result = 0;
+ while ((std::size_t{1} << result) < value)
+ ++result;
+ return result;
+}
+
+inline void expect_token(std::istream &input, const std::string &expected) {
+ std::string actual;
+ if (!(input >> actual) || actual != expected) {
+ throw std::runtime_error("malformed input: expected token " + expected);
+ }
+}
+
+inline InputData read_input(const std::string &path) {
+ std::ifstream input(path);
+ if (!input)
+ throw std::runtime_error("cannot open kernel input");
+ InputData data;
+ expect_token(input, "KBE_INPUT_V1");
+ expect_token(input, "workload");
+ if (!(input >> data.workload_id) || data.workload_id.empty()) {
+ throw std::runtime_error("malformed workload id");
+ }
+ expect_token(input, "dimension");
+ if (!(input >> data.dimension) || !is_power_of_two(data.dimension) ||
+ data.dimension > 64) {
+ throw std::runtime_error("dimension must be a power of two in [2, 64]");
+ }
+ expect_token(input, "matrix_scale");
+ if (!(input >> data.matrix_scale) || data.matrix_scale <= 0) {
+ throw std::runtime_error("matrix_scale must be positive");
+ }
+ expect_token(input, "epsilon_numerator");
+ if (!(input >> data.epsilon_numerator) || data.epsilon_numerator <= 0) {
+ throw std::runtime_error("epsilon_numerator must be positive");
+ }
+ expect_token(input, "matrix");
+ const std::size_t entries = data.dimension * data.dimension;
+ data.matrix.resize(entries);
+ for (std::size_t index = 0; index < entries; ++index) {
+ if (!(input >> data.matrix[index]) ||
+ std::llabs(data.matrix[index]) > data.matrix_scale) {
+ throw std::runtime_error("invalid fixed-point matrix entry");
+ }
+ }
+ expect_token(input, "end");
+ std::string trailing;
+ if (input >> trailing)
+ throw std::runtime_error("trailing kernel input data");
+ return data;
+}
+
+inline std::uint64_t gray_code(std::uint64_t value) {
+ return value ^ (value >> 1U);
+}
+
+inline unsigned popcount64(std::uint64_t value) {
+#if defined(__GNUC__) || defined(__clang__)
+ return static_cast(__builtin_popcountll(value));
+#else
+ unsigned count = 0;
+ while (value != 0) {
+ value &= value - 1;
+ ++count;
+ }
+ return count;
+#endif
+}
+
+inline unsigned trailing_zeroes64(std::uint64_t value) {
+ if (value == 0)
+ throw std::runtime_error("zero has no toggled Gray-code bit");
+#if defined(__GNUC__) || defined(__clang__)
+ return static_cast(__builtin_ctzll(value));
+#else
+ unsigned count = 0;
+ while ((value & 1U) == 0U) {
+ value >>= 1U;
+ ++count;
+ }
+ return count;
+#endif
+}
+
+struct ResourceEstimate {
+ std::uint64_t rotations = 0;
+ std::uint64_t oracle_cnots = 0;
+ std::uint64_t cnots = 0;
+ std::uint64_t hadamards = 0;
+ std::uint64_t depth = 0;
+ std::uint64_t qubits = 0;
+ long double alpha = 0.0L;
+ long double compiled_cost = 0.0L;
+ long double objective = 0.0L;
+};
+
+class Construction {
+public:
+ Construction(std::string input_path, std::string certificate_path)
+ : input_(read_input(input_path)),
+ certificate_path_(std::move(certificate_path)) {
+ qubits_ = integer_log2(input_.dimension);
+ set_basis_mask(0);
+ }
+
+ std::size_t dimension() const { return input_.dimension; }
+ std::size_t system_qubits() const { return qubits_; }
+ std::size_t coefficient_count() const {
+ return input_.dimension * input_.dimension;
+ }
+ std::uint32_t basis_mask() const { return basis_mask_; }
+ std::int64_t matrix_scale() const { return input_.matrix_scale; }
+ std::int64_t minimum_scale_numerator() const {
+ return minimum_scale_numerator_;
+ }
+ std::int64_t scale_numerator() const { return scale_numerator_; }
+ std::int64_t basis_denominator_multiplier() const {
+ return basis_denominator_multiplier_;
+ }
+ long double epsilon() const {
+ return static_cast(input_.epsilon_numerator) /
+ static_cast(input_.matrix_scale);
+ }
+ const std::string &workload_id() const { return input_.workload_id; }
+
+ long double target(std::size_t row, std::size_t column) const {
+ check_matrix_index(row, column);
+ return static_cast(
+ input_.matrix[row * input_.dimension + column]) /
+ static_cast(input_.matrix_scale);
+ }
+
+ long double basis_target(std::size_t row, std::size_t column) const {
+ check_matrix_index(row, column);
+ return static_cast(
+ basis_numerators_[row * input_.dimension + column]) /
+ basis_denominator();
+ }
+
+ void set_basis_mask(std::uint32_t mask) {
+ const std::uint32_t valid_mask =
+ static_cast(input_.dimension - 1U);
+ if ((mask & ~valid_mask) != 0U) {
+ throw std::runtime_error(
+ "basis mask addresses a nonexistent system qubit");
+ }
+ basis_mask_ = mask;
+ basis_numerators_ = input_.matrix;
+ basis_denominator_multiplier_ = 1;
+ for (std::size_t bit = 0; bit < qubits_; ++bit) {
+ if ((mask & (std::uint32_t{1} << bit)) == 0U)
+ continue;
+ apply_row_butterfly(bit);
+ apply_column_butterfly(bit);
+ basis_denominator_multiplier_ *= 2;
+ }
+ minimum_scale_numerator_ = 0;
+ for (const std::int64_t value : basis_numerators_) {
+ minimum_scale_numerator_ =
+ std::max(minimum_scale_numerator_,
+ static_cast(std::llabs(value)));
+ }
+ if (minimum_scale_numerator_ <= 0) {
+ throw std::runtime_error("kernel transformed to an all-zero matrix");
+ }
+ scale_numerator_ = minimum_scale_numerator_;
+ committed_ = false;
+ committed_angles_.clear();
+ }
+
+ void set_scale_numerator(std::int64_t numerator) {
+ if (minimum_scale_numerator_ >
+ std::numeric_limits::max() / kMaximumScaleMultiplier) {
+ throw std::runtime_error("normalization scale range overflows int64");
+ }
+ const std::int64_t maximum =
+ minimum_scale_numerator_ * kMaximumScaleMultiplier;
+ if (numerator < minimum_scale_numerator_ || numerator > maximum) {
+ throw std::runtime_error(
+ "normalization scale is outside the public range");
+ }
+ scale_numerator_ = numerator;
+ committed_ = false;
+ committed_angles_.clear();
+ }
+
+ void set_scale_multiplier(long double multiplier) {
+ if (!std::isfinite(multiplier) || multiplier < 1.0L ||
+ multiplier > static_cast(kMaximumScaleMultiplier)) {
+ throw std::runtime_error("normalization multiplier must lie in [1, 16]");
+ }
+ const long double requested =
+ static_cast(minimum_scale_numerator_) * multiplier;
+ const auto numerator = static_cast(std::ceil(requested));
+ set_scale_numerator(std::max(numerator, minimum_scale_numerator_));
+ }
+
+ std::vector exact_angle_ticks() const {
+ const std::size_t count = coefficient_count();
+ std::vector transformed(count);
+ for (std::size_t index = 0; index < count; ++index) {
+ long double normalized =
+ static_cast(basis_numerators_[index]) /
+ static_cast(scale_numerator_);
+ normalized = std::max(-1.0L, std::min(1.0L, normalized));
+ transformed[index] = 2.0L * std::acos(normalized);
+ }
+ scaled_walsh_hadamard(transformed);
+ const long double pi = std::acos(-1.0L);
+ std::vector result(count, 0);
+ for (std::size_t index = 0; index < count; ++index) {
+ const long double ticks = transformed[gray_code(index)] *
+ static_cast(kAngleDenominator) /
+ pi;
+ if (!std::isfinite(ticks) ||
+ std::fabs(ticks) > static_cast(kMaximumAngleTicks)) {
+ throw std::runtime_error(
+ "generated angle lies outside certificate range");
+ }
+ result[index] = static_cast(std::llround(ticks));
+ }
+ return result;
+ }
+
+ long double
+ frobenius_error(const std::vector &angle_ticks) const {
+ validate_angles(angle_ticks);
+ const std::vector entry_angle_ticks =
+ inverse_angle_transform(angle_ticks);
+ const long double pi = std::acos(-1.0L);
+ const long double scale = static_cast(scale_numerator_);
+ long double squared_error = 0.0L;
+ for (std::size_t index = 0; index < coefficient_count(); ++index) {
+ const long double approximate_numerator =
+ scale *
+ std::cos(pi * static_cast(entry_angle_ticks[index]) /
+ (2.0L * static_cast(kAngleDenominator)));
+ const long double residual =
+ (static_cast(basis_numerators_[index]) -
+ approximate_numerator) /
+ basis_denominator();
+ squared_error += residual * residual;
+ }
+ return std::sqrt(std::max(0.0L, squared_error));
+ }
+
+ ResourceEstimate
+ resources(const std::vector &angle_ticks) const {
+ validate_angles(angle_ticks);
+ ResourceEstimate estimate;
+ const std::size_t count = coefficient_count();
+ const std::size_t controls = 2 * qubits_;
+ std::size_t index = 0;
+ while (index < count) {
+ std::uint64_t parity = 0;
+ if (angle_ticks[index] != 0)
+ ++estimate.rotations;
+ while (true) {
+ unsigned bit = 0;
+ if (index + 1 == count) {
+ bit = static_cast(controls - 1);
+ } else {
+ bit = trailing_zeroes64(gray_code(index) ^ gray_code(index + 1));
+ }
+ parity ^= std::uint64_t{1} << bit;
+ ++index;
+ if (index >= count || angle_ticks[index] != 0)
+ break;
+ }
+ estimate.oracle_cnots += popcount64(parity);
+ }
+ estimate.cnots = estimate.oracle_cnots + 3 * qubits_;
+ estimate.hadamards =
+ 2 * qubits_ + 2 * popcount64(static_cast(basis_mask_));
+ estimate.depth = estimate.rotations + estimate.oracle_cnots + 5 +
+ (basis_mask_ == 0 ? 0 : 2);
+ estimate.qubits = 2 * qubits_ + 1;
+ estimate.alpha = static_cast(input_.dimension) *
+ static_cast(scale_numerator_) /
+ basis_denominator();
+ estimate.compiled_cost =
+ kRotationWeight * static_cast(estimate.rotations) +
+ kCnotWeight * static_cast(estimate.cnots) +
+ kHadamardWeight * static_cast(estimate.hadamards) +
+ kDepthWeight * static_cast(estimate.depth);
+ estimate.objective = estimate.alpha * estimate.compiled_cost;
+ return estimate;
+ }
+
+ long double objective(const std::vector &angle_ticks) const {
+ return resources(angle_ticks).objective;
+ }
+
+ void commit(std::vector angle_ticks) {
+ validate_angles(angle_ticks);
+ committed_angles_ = std::move(angle_ticks);
+ committed_ = true;
+ }
+
+ void write_certificate() const {
+ if (!committed_) {
+ throw std::runtime_error("optimizer did not commit a construction");
+ }
+ std::ofstream output(certificate_path_, std::ios::trunc);
+ if (!output)
+ throw std::runtime_error("cannot create construction certificate");
+ std::size_t nonzero = 0;
+ for (const auto tick : committed_angles_) {
+ if (tick != 0)
+ ++nonzero;
+ }
+ output << "KBE_CERTIFICATE_V1\n"
+ << "dimension " << input_.dimension << '\n'
+ << "basis_mask " << basis_mask_ << '\n'
+ << "scale_numerator " << scale_numerator_ << '\n'
+ << "angle_denominator " << kAngleDenominator << '\n'
+ << "nonzero_count " << nonzero << '\n'
+ << "angles\n";
+ for (std::size_t index = 0; index < committed_angles_.size(); ++index) {
+ if (committed_angles_[index] != 0) {
+ output << index << ' ' << committed_angles_[index] << '\n';
+ }
+ }
+ output << "end\n";
+ output.flush();
+ if (!output)
+ throw std::runtime_error("failed to write construction certificate");
+ }
+
+private:
+ long double basis_denominator() const {
+ return static_cast(input_.matrix_scale) *
+ static_cast(basis_denominator_multiplier_);
+ }
+
+ void check_matrix_index(std::size_t row, std::size_t column) const {
+ if (row >= input_.dimension || column >= input_.dimension) {
+ throw std::out_of_range("kernel matrix index out of range");
+ }
+ }
+
+ static std::int64_t checked_add(std::int64_t lhs, std::int64_t rhs) {
+ const auto minimum = std::numeric_limits::min();
+ const auto maximum = std::numeric_limits::max();
+ if ((rhs > 0 && lhs > maximum - rhs) || (rhs < 0 && lhs < minimum - rhs)) {
+ throw std::runtime_error("integer overflow in basis transform");
+ }
+ return lhs + rhs;
+ }
+
+ static std::int64_t checked_subtract(std::int64_t lhs, std::int64_t rhs) {
+ const auto minimum = std::numeric_limits::min();
+ const auto maximum = std::numeric_limits::max();
+ if ((rhs > 0 && lhs < minimum + rhs) || (rhs < 0 && lhs > maximum + rhs)) {
+ throw std::runtime_error("integer overflow in basis transform");
+ }
+ return lhs - rhs;
+ }
+
+ void apply_row_butterfly(std::size_t bit) {
+ const std::size_t stride = std::size_t{1} << bit;
+ const std::size_t block = 2 * stride;
+ for (std::size_t base = 0; base < input_.dimension; base += block) {
+ for (std::size_t offset = 0; offset < stride; ++offset) {
+ const std::size_t row0 = base + offset;
+ const std::size_t row1 = row0 + stride;
+ for (std::size_t column = 0; column < input_.dimension; ++column) {
+ const std::size_t index0 = row0 * input_.dimension + column;
+ const std::size_t index1 = row1 * input_.dimension + column;
+ const std::int64_t lhs = basis_numerators_[index0];
+ const std::int64_t rhs = basis_numerators_[index1];
+ basis_numerators_[index0] = checked_add(lhs, rhs);
+ basis_numerators_[index1] = checked_subtract(lhs, rhs);
+ }
+ }
+ }
+ }
+
+ void apply_column_butterfly(std::size_t bit) {
+ const std::size_t stride = std::size_t{1} << bit;
+ const std::size_t block = 2 * stride;
+ for (std::size_t row = 0; row < input_.dimension; ++row) {
+ for (std::size_t base = 0; base < input_.dimension; base += block) {
+ for (std::size_t offset = 0; offset < stride; ++offset) {
+ const std::size_t column0 = base + offset;
+ const std::size_t column1 = column0 + stride;
+ const std::size_t index0 = row * input_.dimension + column0;
+ const std::size_t index1 = row * input_.dimension + column1;
+ const std::int64_t lhs = basis_numerators_[index0];
+ const std::int64_t rhs = basis_numerators_[index1];
+ basis_numerators_[index0] = checked_add(lhs, rhs);
+ basis_numerators_[index1] = checked_subtract(lhs, rhs);
+ }
+ }
+ }
+ }
+
+ static void scaled_walsh_hadamard(std::vector &values) {
+ for (std::size_t stride = 1; stride < values.size(); stride *= 2) {
+ for (std::size_t base = 0; base < values.size(); base += 2 * stride) {
+ for (std::size_t offset = 0; offset < stride; ++offset) {
+ const long double lhs = values[base + offset];
+ const long double rhs = values[base + offset + stride];
+ values[base + offset] = (lhs + rhs) / 2.0L;
+ values[base + offset + stride] = (lhs - rhs) / 2.0L;
+ }
+ }
+ }
+ }
+
+ void validate_angles(const std::vector &angle_ticks) const {
+ if (angle_ticks.size() != coefficient_count()) {
+ throw std::runtime_error("angle vector has invalid size");
+ }
+ for (const auto tick : angle_ticks) {
+ if (std::llabs(tick) > kMaximumAngleTicks) {
+ throw std::runtime_error("angle tick lies outside certificate range");
+ }
+ }
+ }
+
+ std::vector
+ inverse_angle_transform(const std::vector &angle_ticks) const {
+ std::vector values(angle_ticks.size(), 0);
+ for (std::size_t index = 0; index < angle_ticks.size(); ++index) {
+ values[gray_code(index)] = angle_ticks[index];
+ }
+ for (std::size_t stride = 1; stride < values.size(); stride *= 2) {
+ for (std::size_t base = 0; base < values.size(); base += 2 * stride) {
+ for (std::size_t offset = 0; offset < stride; ++offset) {
+ const std::int64_t lhs = values[base + offset];
+ const std::int64_t rhs = values[base + offset + stride];
+ values[base + offset] = checked_add(lhs, rhs);
+ values[base + offset + stride] = checked_subtract(lhs, rhs);
+ }
+ }
+ }
+ return values;
+ }
+
+ InputData input_;
+ std::string certificate_path_;
+ std::size_t qubits_ = 0;
+ std::uint32_t basis_mask_ = 0;
+ std::int64_t basis_denominator_multiplier_ = 1;
+ std::vector basis_numerators_;
+ std::int64_t minimum_scale_numerator_ = 0;
+ std::int64_t scale_numerator_ = 0;
+ bool committed_ = false;
+ std::vector committed_angles_;
+};
+
+} // namespace kernel_block_encoding
+
+#endif // KERNEL_BLOCK_ENCODING_CONSTRUCTION_RUNTIME_HPP
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/verification/evaluator.py b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/evaluator.py
new file mode 100644
index 00000000..b748bc26
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/evaluator.py
@@ -0,0 +1,1149 @@
+"""Independent evaluator for resource-aware kernel block encodings."""
+
+from __future__ import annotations
+
+import argparse
+import hashlib
+import json
+import math
+import os
+import re
+import shutil
+import signal
+import subprocess
+import sys
+import tempfile
+import time
+from dataclasses import dataclass
+from decimal import Decimal, ROUND_CEILING, ROUND_HALF_EVEN, localcontext
+from pathlib import Path
+from typing import Any, Callable
+
+
+TASK_DIR = Path(__file__).resolve().parents[1]
+CONFIG_PATH = TASK_DIR / "references" / "problem_config.json"
+BASELINE_PATH = TASK_DIR / "baseline" / "solution.cpp"
+RUNTIME_INCLUDE = TASK_DIR / "verification"
+LIMITED_EXEC = RUNTIME_INCLUDE / "limited_exec.py"
+START_MARKER = "// EVOLVE-BLOCK-START"
+END_MARKER = "// EVOLVE-BLOCK-END"
+INTEGER_RE = re.compile(r"-?(?:0|[1-9][0-9]*)\Z")
+
+
+class EvaluationError(RuntimeError):
+ """A deterministic source, process, certificate, or validity failure."""
+
+
+def _strict_json(path: Path) -> dict[str, Any]:
+ def reject_constant(value: str) -> None:
+ raise ValueError(f"non-finite JSON constant is not allowed: {value}")
+
+ data = json.loads(path.read_text(encoding="utf-8"), parse_constant=reject_constant)
+ if not isinstance(data, dict):
+ raise ValueError("configuration root must be an object")
+ return data
+
+
+def _positive_int(value: Any, label: str) -> int:
+ if isinstance(value, bool) or not isinstance(value, int) or value <= 0:
+ raise ValueError(f"{label} must be a positive integer")
+ return value
+
+
+def _finite_float(value: Any, label: str) -> float:
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
+ raise ValueError(f"{label} must be a finite number")
+ result = float(value)
+ if not math.isfinite(result):
+ raise ValueError(f"{label} must be finite")
+ return result
+
+
+def _power_of_two(value: int) -> bool:
+ return value >= 2 and value & (value - 1) == 0
+
+
+def _validated_config() -> dict[str, Any]:
+ config = _strict_json(CONFIG_PATH)
+ if config.get("benchmark_id") != "kernel_block_encoding":
+ raise ValueError("unexpected benchmark_id")
+ matrix_scale = _positive_int(config.get("matrix_scale"), "matrix_scale")
+ angle_denominator = _positive_int(
+ config.get("angle_denominator"), "angle_denominator"
+ )
+ if angle_denominator != 1 << 28:
+ raise ValueError("angle_denominator does not match the frozen C++ runtime")
+ objective = config.get("objective")
+ limits = config.get("limits")
+ workloads = config.get("workloads")
+ if not isinstance(objective, dict) or not isinstance(limits, dict):
+ raise ValueError("objective and limits must be objects")
+ if not isinstance(workloads, list) or not workloads:
+ raise ValueError("workloads must be a non-empty list")
+ frozen_weights = {
+ "rotation_weight": 16.0,
+ "cnot_weight": 1.0,
+ "hadamard_weight": 0.25,
+ "depth_weight": 0.25,
+ }
+ for key, frozen_value in frozen_weights.items():
+ value = _finite_float(objective.get(key), key)
+ if value <= 0.0:
+ raise ValueError(f"{key} must be positive")
+ if value != frozen_value:
+ raise ValueError(f"{key} does not match the frozen C++ runtime")
+ normalization_exponent = _finite_float(
+ objective.get("normalization_exponent"), "normalization_exponent"
+ )
+ if normalization_exponent <= 0:
+ raise ValueError("normalization_exponent must be positive")
+ if normalization_exponent != 1.0:
+ raise ValueError("normalization_exponent does not match the frozen runtime")
+ for key in (
+ "max_candidate_bytes",
+ "max_certificate_bytes",
+ "max_dimension",
+ "max_processes",
+ "max_scale_multiplier",
+ "memory_limit_mb",
+ ):
+ _positive_int(limits.get(key), key)
+ if int(limits["max_scale_multiplier"]) != 16:
+ raise ValueError("max_scale_multiplier does not match the frozen C++ runtime")
+ if _finite_float(limits.get("candidate_timeout_s_per_workload"), "candidate timeout") <= 0:
+ raise ValueError("candidate timeout must be positive")
+ if _finite_float(limits.get("compile_timeout_s"), "compile timeout") <= 0:
+ raise ValueError("compile timeout must be positive")
+
+ ids: set[str] = set()
+ supported = {"rbf", "multiscale_rbf", "polynomial", "rational_quadratic", "walk_gram"}
+ for index, spec in enumerate(workloads):
+ if not isinstance(spec, dict):
+ raise ValueError(f"workloads[{index}] must be an object")
+ workload_id = str(spec.get("id", ""))
+ kind = str(spec.get("kind", ""))
+ dimension = _positive_int(spec.get("dimension"), f"{workload_id}.dimension")
+ if (
+ not workload_id
+ or workload_id in ids
+ or not re.fullmatch(r"[a-z0-9_]+", workload_id)
+ or kind not in supported
+ or not _power_of_two(dimension)
+ or dimension > int(limits["max_dimension"])
+ ):
+ raise ValueError(f"invalid workload at index {index}")
+ relative_error_ppm = _positive_int(
+ spec.get("relative_error_ppm"), f"{workload_id}.relative_error_ppm"
+ )
+ if relative_error_ppm >= 1_000_000:
+ raise ValueError("relative error must be below one")
+ expected = str(spec.get("expected_sha256", ""))
+ if not re.fullmatch(r"[0-9a-f]{64}", expected):
+ raise ValueError(f"invalid expected_sha256 for {workload_id}")
+ ids.add(workload_id)
+ if matrix_scale > 1 << 30:
+ raise ValueError("matrix_scale is unexpectedly large")
+ return config
+
+
+class Lcg:
+ """Tiny specified PRNG used only to build deterministic integer features."""
+
+ def __init__(self, seed: int) -> None:
+ self.state = seed & ((1 << 64) - 1)
+
+ def next_u64(self) -> int:
+ self.state = (
+ 6364136223846793005 * self.state + 1442695040888963407
+ ) & ((1 << 64) - 1)
+ return self.state
+
+ def bounded(self, low: int, high: int) -> int:
+ if low > high:
+ raise ValueError("invalid PRNG range")
+ return low + self.next_u64() % (high - low + 1)
+
+
+def _clustered_features(spec: dict[str, Any]) -> list[list[int]]:
+ dimension = _positive_int(spec.get("dimension"), "dimension")
+ feature_dimensions = _positive_int(
+ spec.get("feature_dimensions"), "feature_dimensions"
+ )
+ clusters = _positive_int(spec.get("clusters"), "clusters")
+ separation = _positive_int(spec.get("cluster_separation"), "cluster_separation")
+ jitter = _positive_int(spec.get("jitter"), "jitter")
+ seed = _positive_int(spec.get("seed"), "seed")
+ if dimension % clusters != 0 or clusters > dimension:
+ raise ValueError("clusters must evenly divide the kernel dimension")
+ random = Lcg(seed)
+ centers: list[list[int]] = []
+ for cluster in range(clusters):
+ center: list[int] = []
+ for axis in range(feature_dimensions):
+ permutation = (cluster * (2 * axis + 1) + 3 * axis) % clusters
+ center.append((2 * permutation - clusters + 1) * separation)
+ centers.append(center)
+ features: list[list[int]] = []
+ per_cluster = dimension // clusters
+ for row in range(dimension):
+ cluster = row // per_cluster
+ features.append(
+ [
+ centers[cluster][axis] + random.bounded(-jitter, jitter)
+ for axis in range(feature_dimensions)
+ ]
+ )
+ return features
+
+
+def _decimal_exp_ticks(exponent: Decimal, matrix_scale: int) -> int:
+ with localcontext() as context:
+ context.prec = 60
+ value = exponent.exp() * Decimal(matrix_scale)
+ return int(value.to_integral_value(rounding=ROUND_HALF_EVEN))
+
+
+def _rbf_matrix(spec: dict[str, Any], matrix_scale: int) -> list[int]:
+ features = _clustered_features(spec)
+ dimension = len(features)
+ bandwidth_squared = _positive_int(
+ spec.get("bandwidth_squared"), "bandwidth_squared"
+ )
+ result = [0] * (dimension * dimension)
+ for row in range(dimension):
+ result[row * dimension + row] = matrix_scale
+ for column in range(row):
+ distance_squared = sum(
+ (axis + 1) * (features[row][axis] - features[column][axis]) ** 2
+ for axis in range(len(features[row]))
+ )
+ exponent = -Decimal(distance_squared) / Decimal(2 * bandwidth_squared)
+ ticks = _decimal_exp_ticks(exponent, matrix_scale)
+ result[row * dimension + column] = ticks
+ result[column * dimension + row] = ticks
+ return result
+
+
+def _multiscale_rbf_matrix(spec: dict[str, Any], matrix_scale: int) -> list[int]:
+ features = _clustered_features(spec)
+ dimension = len(features)
+ small = _positive_int(
+ spec.get("bandwidth_squared_small"), "bandwidth_squared_small"
+ )
+ large = _positive_int(
+ spec.get("bandwidth_squared_large"), "bandwidth_squared_large"
+ )
+ weight_num = _positive_int(
+ spec.get("small_weight_numerator"), "small_weight_numerator"
+ )
+ weight_den = _positive_int(spec.get("weight_denominator"), "weight_denominator")
+ if weight_num >= weight_den:
+ raise ValueError("small kernel weight must lie strictly between zero and one")
+ result = [0] * (dimension * dimension)
+ with localcontext() as context:
+ context.prec = 60
+ weight = Decimal(weight_num) / Decimal(weight_den)
+ for row in range(dimension):
+ result[row * dimension + row] = matrix_scale
+ for column in range(row):
+ distance_squared = sum(
+ (axis + 1) * (features[row][axis] - features[column][axis]) ** 2
+ for axis in range(len(features[row]))
+ )
+ fine = (-Decimal(distance_squared) / Decimal(2 * small)).exp()
+ coarse = (-Decimal(distance_squared) / Decimal(2 * large)).exp()
+ value = (weight * fine + (Decimal(1) - weight) * coarse) * Decimal(
+ matrix_scale
+ )
+ ticks = int(value.to_integral_value(rounding=ROUND_HALF_EVEN))
+ result[row * dimension + column] = ticks
+ result[column * dimension + row] = ticks
+ return result
+
+
+def _round_ratio(numerator: int, denominator: int) -> int:
+ if denominator <= 0:
+ raise ValueError("ratio denominator must be positive")
+ sign = -1 if numerator < 0 else 1
+ magnitude = abs(numerator)
+ quotient, remainder = divmod(magnitude, denominator)
+ if 2 * remainder > denominator or (
+ 2 * remainder == denominator and quotient % 2 == 1
+ ):
+ quotient += 1
+ return sign * quotient
+
+
+def _polynomial_matrix(spec: dict[str, Any], matrix_scale: int) -> list[int]:
+ dimension = _positive_int(spec.get("dimension"), "dimension")
+ feature_dimensions = _positive_int(
+ spec.get("feature_dimensions"), "feature_dimensions"
+ )
+ feature_bound = _positive_int(spec.get("feature_bound"), "feature_bound")
+ bias = _positive_int(spec.get("bias"), "bias")
+ degree = _positive_int(spec.get("degree"), "degree")
+ seed = _positive_int(spec.get("seed"), "seed")
+ random = Lcg(seed)
+ features = [
+ [random.bounded(-feature_bound, feature_bound) for _ in range(feature_dimensions)]
+ for _ in range(dimension)
+ ]
+ raw: list[int] = []
+ for row in range(dimension):
+ for column in range(dimension):
+ inner = bias + sum(
+ features[row][axis] * features[column][axis]
+ for axis in range(feature_dimensions)
+ )
+ raw.append(inner**degree)
+ normalization = max(raw[index * dimension + index] for index in range(dimension))
+ if normalization <= 0:
+ raise ValueError("polynomial Gram matrix has invalid diagonal")
+ return [_round_ratio(value * matrix_scale, normalization) for value in raw]
+
+
+def _rational_quadratic_matrix(
+ spec: dict[str, Any], matrix_scale: int
+) -> list[int]:
+ dimension = _positive_int(spec.get("dimension"), "dimension")
+ feature_dimensions = _positive_int(
+ spec.get("feature_dimensions"), "feature_dimensions"
+ )
+ feature_bound = _positive_int(spec.get("feature_bound"), "feature_bound")
+ length_squared = _positive_int(spec.get("length_squared"), "length_squared")
+ seed = _positive_int(spec.get("seed"), "seed")
+ random = Lcg(seed)
+ features = [
+ [random.bounded(-feature_bound, feature_bound) for _ in range(feature_dimensions)]
+ for _ in range(dimension)
+ ]
+ result: list[int] = []
+ for row in range(dimension):
+ for column in range(dimension):
+ distance_squared = sum(
+ (features[row][axis] - features[column][axis]) ** 2
+ for axis in range(feature_dimensions)
+ )
+ result.append(
+ _round_ratio(
+ matrix_scale * 2 * length_squared,
+ 2 * length_squared + distance_squared,
+ )
+ )
+ return result
+
+
+def _matrix_multiply(lhs: list[list[int]], rhs: list[list[int]]) -> list[list[int]]:
+ size = len(lhs)
+ return [
+ [
+ sum(lhs[row][inner] * rhs[inner][column] for inner in range(size))
+ for column in range(size)
+ ]
+ for row in range(size)
+ ]
+
+
+def _walk_gram_matrix(spec: dict[str, Any], matrix_scale: int) -> list[int]:
+ dimension = _positive_int(spec.get("dimension"), "dimension")
+ shortcut = _positive_int(spec.get("shortcut_stride"), "shortcut_stride")
+ walk_steps = _positive_int(spec.get("walk_steps"), "walk_steps")
+ self_weight = _positive_int(spec.get("self_weight"), "self_weight")
+ transition = [[0] * dimension for _ in range(dimension)]
+ for row in range(dimension):
+ transition[row][row] += self_weight
+ transition[row][(row - 1) % dimension] += 1
+ transition[row][(row + 1) % dimension] += 1
+ transition[row][(row + shortcut) % dimension] += 1
+ transition[row][(row - shortcut) % dimension] += 1
+ current = [[int(row == column) for column in range(dimension)] for row in range(dimension)]
+ gram = [[0] * dimension for _ in range(dimension)]
+ for _ in range(walk_steps + 1):
+ for row in range(dimension):
+ for column in range(dimension):
+ gram[row][column] += sum(
+ current[row][feature] * current[column][feature]
+ for feature in range(dimension)
+ )
+ current = _matrix_multiply(current, transition)
+ normalization = max(gram[index][index] for index in range(dimension))
+ return [
+ _round_ratio(gram[row][column] * matrix_scale, normalization)
+ for row in range(dimension)
+ for column in range(dimension)
+ ]
+
+
+MATRIX_GENERATORS: dict[str, Callable[[dict[str, Any], int], list[int]]] = {
+ "rbf": _rbf_matrix,
+ "multiscale_rbf": _multiscale_rbf_matrix,
+ "polynomial": _polynomial_matrix,
+ "rational_quadratic": _rational_quadratic_matrix,
+ "walk_gram": _walk_gram_matrix,
+}
+
+
+@dataclass(frozen=True)
+class Workload:
+ workload_id: str
+ dimension: int
+ matrix_scale: int
+ epsilon_numerator: int
+ matrix: tuple[int, ...]
+ input_bytes: bytes
+ sha256: str
+
+ @property
+ def epsilon(self) -> float:
+ return self.epsilon_numerator / self.matrix_scale
+
+
+def _build_workload(spec: dict[str, Any], matrix_scale: int) -> Workload:
+ workload_id = str(spec["id"])
+ dimension = int(spec["dimension"])
+ generator = MATRIX_GENERATORS[str(spec["kind"])]
+ matrix = generator(spec, matrix_scale)
+ if len(matrix) != dimension * dimension:
+ raise ValueError(f"generator returned wrong matrix size for {workload_id}")
+ if any(abs(value) > matrix_scale for value in matrix):
+ raise ValueError(f"kernel entry exceeds fixed-point range for {workload_id}")
+ for row in range(dimension):
+ for column in range(dimension):
+ if matrix[row * dimension + column] != matrix[column * dimension + row]:
+ raise ValueError(f"kernel is not symmetric for {workload_id}")
+ squared_norm = sum(value * value for value in matrix)
+ with localcontext() as context:
+ context.prec = 60
+ epsilon_numerator = int(
+ (
+ Decimal(squared_norm).sqrt()
+ * Decimal(int(spec["relative_error_ppm"]))
+ / Decimal(1_000_000)
+ ).to_integral_value(rounding=ROUND_CEILING)
+ )
+ lines = [
+ "KBE_INPUT_V1",
+ f"workload {workload_id}",
+ f"dimension {dimension}",
+ f"matrix_scale {matrix_scale}",
+ f"epsilon_numerator {epsilon_numerator}",
+ "matrix",
+ ]
+ for row in range(dimension):
+ lines.append(
+ " ".join(
+ str(matrix[row * dimension + column])
+ for column in range(dimension)
+ )
+ )
+ lines.append("end")
+ input_bytes = ("\n".join(lines) + "\n").encode("ascii")
+ digest = hashlib.sha256(input_bytes).hexdigest()
+ expected = str(spec.get("expected_sha256", ""))
+ if digest != expected:
+ raise EvaluationError(f"frozen workload digest mismatch for {workload_id}")
+ return Workload(
+ workload_id=workload_id,
+ dimension=dimension,
+ matrix_scale=matrix_scale,
+ epsilon_numerator=epsilon_numerator,
+ matrix=tuple(matrix),
+ input_bytes=input_bytes,
+ sha256=digest,
+ )
+
+
+def _basis_transform(
+ matrix: tuple[int, ...] | list[int], dimension: int, mask: int
+) -> tuple[list[int], int]:
+ values = list(matrix)
+ denominator_multiplier = 1
+ qubits = dimension.bit_length() - 1
+ for bit in range(qubits):
+ if mask & (1 << bit) == 0:
+ continue
+ stride = 1 << bit
+ block = 2 * stride
+ for base in range(0, dimension, block):
+ for offset in range(stride):
+ row0 = base + offset
+ row1 = row0 + stride
+ for column in range(dimension):
+ index0 = row0 * dimension + column
+ index1 = row1 * dimension + column
+ lhs, rhs = values[index0], values[index1]
+ values[index0], values[index1] = lhs + rhs, lhs - rhs
+ for row in range(dimension):
+ for base in range(0, dimension, block):
+ for offset in range(stride):
+ column0 = base + offset
+ column1 = column0 + stride
+ index0 = row * dimension + column0
+ index1 = row * dimension + column1
+ lhs, rhs = values[index0], values[index1]
+ values[index0], values[index1] = lhs + rhs, lhs - rhs
+ denominator_multiplier *= 2
+ return values, denominator_multiplier
+
+
+def _gray_code(value: int) -> int:
+ return value ^ (value >> 1)
+
+
+def _inverse_angle_transform(angle_ticks: list[int]) -> list[int]:
+ values = [0] * len(angle_ticks)
+ for index, tick in enumerate(angle_ticks):
+ values[_gray_code(index)] = tick
+ stride = 1
+ while stride < len(values):
+ for base in range(0, len(values), 2 * stride):
+ for offset in range(stride):
+ lhs = values[base + offset]
+ rhs = values[base + offset + stride]
+ values[base + offset] = lhs + rhs
+ values[base + offset + stride] = lhs - rhs
+ stride *= 2
+ return values
+
+
+@dataclass(frozen=True)
+class Certificate:
+ basis_mask: int
+ scale_numerator: int
+ angle_ticks: tuple[int, ...]
+ sha256: str
+ byte_count: int
+
+
+def _parse_integer(token: str, label: str) -> int:
+ if INTEGER_RE.fullmatch(token) is None or token == "-0":
+ raise EvaluationError(f"{label} is not a canonical decimal integer")
+ return int(token)
+
+
+def _parse_certificate(
+ certificate_bytes: bytes,
+ workload: Workload,
+ config: dict[str, Any],
+) -> Certificate:
+ try:
+ text = certificate_bytes.decode("ascii")
+ except UnicodeDecodeError as exc:
+ raise EvaluationError("certificate is not ASCII") from exc
+ tokens = text.split()
+ cursor = 0
+
+ def take(expected: str | None = None) -> str:
+ nonlocal cursor
+ if cursor >= len(tokens):
+ raise EvaluationError("truncated construction certificate")
+ token = tokens[cursor]
+ cursor += 1
+ if expected is not None and token != expected:
+ raise EvaluationError(f"expected certificate token {expected}")
+ return token
+
+ take("KBE_CERTIFICATE_V1")
+ take("dimension")
+ dimension = _parse_integer(take(), "dimension")
+ take("basis_mask")
+ basis_mask = _parse_integer(take(), "basis_mask")
+ take("scale_numerator")
+ scale_numerator = _parse_integer(take(), "scale_numerator")
+ take("angle_denominator")
+ angle_denominator = _parse_integer(take(), "angle_denominator")
+ take("nonzero_count")
+ nonzero_count = _parse_integer(take(), "nonzero_count")
+ take("angles")
+ if dimension != workload.dimension:
+ raise EvaluationError("certificate dimension does not match workload")
+ if basis_mask < 0 or basis_mask >= dimension:
+ raise EvaluationError("basis mask addresses a nonexistent system qubit")
+ if angle_denominator != int(config["angle_denominator"]):
+ raise EvaluationError("certificate angle denominator is not frozen value")
+ coefficient_count = dimension * dimension
+ if nonzero_count < 0 or nonzero_count > coefficient_count:
+ raise EvaluationError("invalid nonzero angle count")
+ angle_ticks = [0] * coefficient_count
+ previous_index = -1
+ maximum_tick = 4 * angle_denominator
+ for _ in range(nonzero_count):
+ index = _parse_integer(take(), "angle index")
+ tick = _parse_integer(take(), "angle tick")
+ if index <= previous_index or index >= coefficient_count:
+ raise EvaluationError("angle indices must be strictly increasing and in range")
+ if tick == 0 or abs(tick) > maximum_tick:
+ raise EvaluationError("invalid nonzero angle tick")
+ angle_ticks[index] = tick
+ previous_index = index
+ take("end")
+ if cursor != len(tokens):
+ raise EvaluationError("trailing construction certificate data")
+ basis_values, _ = _basis_transform(workload.matrix, dimension, basis_mask)
+ minimum_scale = max(abs(value) for value in basis_values)
+ maximum_scale = minimum_scale * int(config["limits"]["max_scale_multiplier"])
+ if scale_numerator < minimum_scale or scale_numerator > maximum_scale:
+ raise EvaluationError("normalization scale is outside the public range")
+ return Certificate(
+ basis_mask=basis_mask,
+ scale_numerator=scale_numerator,
+ angle_ticks=tuple(angle_ticks),
+ sha256=hashlib.sha256(certificate_bytes).hexdigest(),
+ byte_count=len(certificate_bytes),
+ )
+
+
+@dataclass(frozen=True)
+class CheckedConstruction:
+ frobenius_error: float
+ error_upper_bound: float
+ relative_error: float
+ alpha: float
+ rotations: int
+ oracle_cnots: int
+ cnots: int
+ hadamards: int
+ depth: int
+ qubits: int
+ compiled_cost: float
+ objective: float
+ basis_denominator_multiplier: int
+ minimum_scale_numerator: int
+
+
+def _check_construction(
+ certificate: Certificate,
+ workload: Workload,
+ config: dict[str, Any],
+) -> CheckedConstruction:
+ dimension = workload.dimension
+ basis_values, denominator_multiplier = _basis_transform(
+ workload.matrix, dimension, certificate.basis_mask
+ )
+ minimum_scale = max(abs(value) for value in basis_values)
+ entry_angle_ticks = _inverse_angle_transform(list(certificate.angle_ticks))
+ angle_denominator = int(config["angle_denominator"])
+ denominator = workload.matrix_scale * denominator_multiplier
+ scale = certificate.scale_numerator / denominator
+ residuals: list[float] = []
+ for target_numerator, theta_tick in zip(basis_values, entry_angle_ticks):
+ approximate_numerator = certificate.scale_numerator * math.cos(
+ math.pi * theta_tick / (2.0 * angle_denominator)
+ )
+ residuals.append((target_numerator - approximate_numerator) / denominator)
+ squared_error = math.fsum(value * value for value in residuals)
+ frobenius_error = math.sqrt(max(0.0, squared_error))
+ numerical_guard = max(
+ 1e-12,
+ dimension * max(1.0, abs(scale)) * 32.0 * math.ulp(1.0),
+ )
+ error_upper_bound = frobenius_error + numerical_guard
+ if error_upper_bound > workload.epsilon:
+ raise EvaluationError(
+ f"block error {error_upper_bound:.9g} exceeds epsilon {workload.epsilon:.9g}"
+ )
+
+ count = dimension * dimension
+ controls = 2 * (dimension.bit_length() - 1)
+ rotations = 0
+ oracle_cnots = 0
+ index = 0
+ while index < count:
+ parity = 0
+ if certificate.angle_ticks[index] != 0:
+ rotations += 1
+ while True:
+ if index + 1 == count:
+ bit = controls - 1
+ else:
+ transition = _gray_code(index) ^ _gray_code(index + 1)
+ bit = (transition & -transition).bit_length() - 1
+ parity ^= 1 << bit
+ index += 1
+ if index >= count or certificate.angle_ticks[index] != 0:
+ break
+ oracle_cnots += parity.bit_count()
+
+ qubits = dimension.bit_length() - 1
+ cnots = oracle_cnots + 3 * qubits
+ hadamards = 2 * qubits + 2 * certificate.basis_mask.bit_count()
+ depth = rotations + oracle_cnots + 5 + (2 if certificate.basis_mask else 0)
+ alpha = dimension * scale
+ objective_config = config["objective"]
+ compiled_cost = (
+ float(objective_config["rotation_weight"]) * rotations
+ + float(objective_config["cnot_weight"]) * cnots
+ + float(objective_config["hadamard_weight"]) * hadamards
+ + float(objective_config["depth_weight"]) * depth
+ )
+ objective = alpha ** float(objective_config["normalization_exponent"]) * compiled_cost
+ if not math.isfinite(objective) or objective <= 0.0:
+ raise EvaluationError("construction has a non-positive or non-finite objective")
+ target_norm = math.sqrt(
+ math.fsum((value / workload.matrix_scale) ** 2 for value in workload.matrix)
+ )
+ return CheckedConstruction(
+ frobenius_error=frobenius_error,
+ error_upper_bound=error_upper_bound,
+ relative_error=error_upper_bound / target_norm,
+ alpha=alpha,
+ rotations=rotations,
+ oracle_cnots=oracle_cnots,
+ cnots=cnots,
+ hadamards=hadamards,
+ depth=depth,
+ qubits=2 * qubits + 1,
+ compiled_cost=compiled_cost,
+ objective=objective,
+ basis_denominator_multiplier=denominator_multiplier,
+ minimum_scale_numerator=minimum_scale,
+ )
+
+
+def _split_source(source: bytes) -> tuple[bytes, bytes, bytes]:
+ if source.count(START_MARKER.encode()) != 1 or source.count(END_MARKER.encode()) != 1:
+ raise EvaluationError("candidate must contain exactly one pair of EVOLVE markers")
+ start = source.index(START_MARKER.encode())
+ end = source.index(END_MARKER.encode(), start)
+ end += len(END_MARKER)
+ return source[:start], source[start:end], source[end:]
+
+
+def _validate_candidate_shell(candidate_path: Path, maximum_bytes: int) -> bytes:
+ if not candidate_path.is_file():
+ raise EvaluationError("candidate C++ source does not exist")
+ source = candidate_path.read_bytes()
+ if not source or len(source) > maximum_bytes:
+ raise EvaluationError("candidate source is empty or exceeds size limit")
+ baseline = BASELINE_PATH.read_bytes()
+ candidate_prefix, _, candidate_suffix = _split_source(source)
+ baseline_prefix, _, baseline_suffix = _split_source(baseline)
+ if candidate_prefix != baseline_prefix or candidate_suffix != baseline_suffix:
+ raise EvaluationError("candidate changed code outside the EVOLVE block")
+ return source
+
+
+def _tail(path: Path, maximum: int = 4000) -> str:
+ if not path.is_file():
+ return ""
+ data = path.read_bytes()
+ return data[-maximum:].decode("utf-8", errors="replace")
+
+
+def _compile(
+ compiler: str,
+ source: Path,
+ output: Path,
+ timeout_s: float,
+ log_path: Path,
+) -> None:
+ command = [
+ compiler,
+ "-std=c++17",
+ "-O2",
+ "-pipe",
+ "-Wall",
+ "-Wextra",
+ "-I",
+ str(RUNTIME_INCLUDE),
+ str(source),
+ "-o",
+ str(output),
+ ]
+ with log_path.open("wb") as log:
+ try:
+ completed = subprocess.run(
+ command,
+ stdout=log,
+ stderr=subprocess.STDOUT,
+ timeout=timeout_s,
+ check=False,
+ env={"PATH": os.environ.get("PATH", ""), "LC_ALL": "C"},
+ )
+ except subprocess.TimeoutExpired as exc:
+ raise EvaluationError(f"compilation timed out after {timeout_s:.1f}s") from exc
+ if completed.returncode != 0:
+ raise EvaluationError(f"compilation failed: {_tail(log_path)}")
+
+
+@dataclass(frozen=True)
+class ProgramRun:
+ certificate: bytes
+ stdout_tail: str
+ elapsed_s: float
+
+
+def _run_program(
+ executable: Path,
+ workload: Workload,
+ run_dir: Path,
+ timeout_s: float,
+ maximum_certificate_bytes: int,
+ memory_mb: int,
+ maximum_processes: int,
+) -> ProgramRun:
+ run_dir.mkdir(parents=True, exist_ok=False)
+ input_path = run_dir / "kernel.kbe"
+ certificate_path = run_dir / "construction.kbc"
+ log_path = run_dir / "candidate.log"
+ input_path.write_bytes(workload.input_bytes)
+ cpu_seconds = max(1, int(math.ceil(timeout_s)) + 1)
+ file_limit = max(maximum_certificate_bytes, 64 * 1024)
+ command = [
+ sys.executable,
+ str(LIMITED_EXEC),
+ str(memory_mb),
+ str(cpu_seconds),
+ str(file_limit),
+ str(maximum_processes),
+ str(run_dir),
+ "--",
+ str(executable),
+ "--input",
+ str(input_path),
+ "--certificate",
+ str(certificate_path),
+ ]
+ started = time.perf_counter()
+ with log_path.open("wb") as log:
+ process = subprocess.Popen(
+ command,
+ stdout=log,
+ stderr=subprocess.STDOUT,
+ close_fds=False,
+ env={"PATH": os.environ.get("PATH", ""), "LC_ALL": "C"},
+ )
+ try:
+ returncode = process.wait(timeout=timeout_s)
+ except subprocess.TimeoutExpired as exc:
+ try:
+ os.killpg(process.pid, signal.SIGKILL)
+ except ProcessLookupError:
+ pass
+ process.wait()
+ raise EvaluationError(f"candidate timed out after {timeout_s:.1f}s") from exc
+ try:
+ # The candidate is session leader. Remove any descendants it left behind
+ # before inspecting the supposedly frozen input and certificate.
+ os.killpg(process.pid, signal.SIGKILL)
+ except ProcessLookupError:
+ pass
+ elapsed = time.perf_counter() - started
+ if returncode != 0:
+ raise EvaluationError(f"candidate exited with code {returncode}: {_tail(log_path)}")
+ if input_path.read_bytes() != workload.input_bytes:
+ raise EvaluationError("candidate modified the frozen kernel input")
+ if not certificate_path.is_file():
+ raise EvaluationError("candidate did not produce a construction certificate")
+ if certificate_path.stat().st_size > maximum_certificate_bytes:
+ raise EvaluationError("construction certificate exceeds size limit")
+ return ProgramRun(
+ certificate=certificate_path.read_bytes(),
+ stdout_tail=_tail(log_path),
+ elapsed_s=elapsed,
+ )
+
+
+def _construction_artifact(
+ certificate: Certificate,
+ checked: CheckedConstruction,
+ run: ProgramRun,
+) -> dict[str, Any]:
+ return {
+ "basis_mask": certificate.basis_mask,
+ "scale_numerator": certificate.scale_numerator,
+ "minimum_scale_numerator": checked.minimum_scale_numerator,
+ "basis_denominator_multiplier": checked.basis_denominator_multiplier,
+ "alpha": checked.alpha,
+ "frobenius_error": checked.frobenius_error,
+ "error_upper_bound": checked.error_upper_bound,
+ "relative_error": checked.relative_error,
+ "rotations": checked.rotations,
+ "oracle_cnots": checked.oracle_cnots,
+ "cnots": checked.cnots,
+ "hadamards": checked.hadamards,
+ "depth": checked.depth,
+ "qubits": checked.qubits,
+ "compiled_cost": checked.compiled_cost,
+ "objective": checked.objective,
+ "nonzero_angles": sum(tick != 0 for tick in certificate.angle_ticks),
+ "certificate_bytes": certificate.byte_count,
+ "certificate_sha256": certificate.sha256,
+ "runtime_s": run.elapsed_s,
+ "stdout_tail": run.stdout_tail,
+ }
+
+
+def _invalid_metrics(runtime_s: float, *, timeout: bool = False) -> dict[str, float]:
+ return {
+ "combined_score": 0.0,
+ "valid": 0.0,
+ "timeout": 1.0 if timeout else 0.0,
+ "runtime_s": float(runtime_s),
+ }
+
+
+def evaluate(
+ candidate_path: Path,
+ *,
+ timeout_override_s: float | None = None,
+) -> tuple[dict[str, float], dict[str, Any]]:
+ started = time.perf_counter()
+ artifacts: dict[str, Any] = {
+ "benchmark_id": "kernel_block_encoding",
+ "checker": "independent analytic FABLE block reconstruction",
+ }
+ try:
+ config = _validated_config()
+ limits = config["limits"]
+ source = _validate_candidate_shell(
+ candidate_path, int(limits["max_candidate_bytes"])
+ )
+ compiler = shutil.which("g++")
+ if compiler is None:
+ raise EvaluationError("g++ is required but was not found on PATH")
+ timeout_s = (
+ float(timeout_override_s)
+ if timeout_override_s is not None
+ else float(limits["candidate_timeout_s_per_workload"])
+ )
+ if timeout_s <= 0.0:
+ raise EvaluationError("candidate timeout must be positive")
+ compile_timeout = float(limits["compile_timeout_s"])
+ matrix_scale = int(config["matrix_scale"])
+ workloads = [_build_workload(spec, matrix_scale) for spec in config["workloads"]]
+ artifacts["workload_manifest"] = [
+ {
+ "id": workload.workload_id,
+ "dimension": workload.dimension,
+ "epsilon": workload.epsilon,
+ "input_bytes": len(workload.input_bytes),
+ "sha256": workload.sha256,
+ }
+ for workload in workloads
+ ]
+
+ with tempfile.TemporaryDirectory(prefix="kernel_block_encoding_eval_") as temporary:
+ temp = Path(temporary)
+ candidate_copy = temp / "candidate.cpp"
+ candidate_copy.write_bytes(source)
+ candidate_executable = temp / "candidate"
+ baseline_executable = temp / "baseline"
+ baseline_compile_log = temp / "baseline_compile.log"
+ candidate_compile_log = temp / "candidate_compile.log"
+ compile_started = time.perf_counter()
+ _compile(
+ compiler,
+ BASELINE_PATH,
+ baseline_executable,
+ compile_timeout,
+ baseline_compile_log,
+ )
+ baseline_compile_s = time.perf_counter() - compile_started
+ compile_started = time.perf_counter()
+ _compile(
+ compiler,
+ candidate_copy,
+ candidate_executable,
+ compile_timeout,
+ candidate_compile_log,
+ )
+ candidate_compile_s = time.perf_counter() - compile_started
+
+ scores: list[float] = []
+ total_candidate_rotations = 0
+ total_candidate_cnots = 0
+ total_baseline_rotations = 0
+ total_baseline_cnots = 0
+ total_checked_entries = 0
+ candidate_alpha_sum = 0.0
+ candidate_checked_scenarios = 0
+ results: dict[str, Any] = {}
+ failure_summaries: list[str] = []
+ failed_workloads: list[str] = []
+ any_timeout = False
+
+ artifacts["compiler"] = compiler
+ artifacts["compile"] = {
+ "baseline_s": baseline_compile_s,
+ "candidate_s": candidate_compile_s,
+ }
+ artifacts["objective"] = config["objective"]
+ artifacts["limits"] = limits
+
+ for index, workload in enumerate(workloads):
+ workload_result: dict[str, Any] = {
+ "epsilon": workload.epsilon,
+ "input_sha256": workload.sha256,
+ }
+ workload_errors: list[str] = []
+ baseline_checked: CheckedConstruction | None = None
+ candidate_checked: CheckedConstruction | None = None
+
+ try:
+ baseline_run = _run_program(
+ baseline_executable,
+ workload,
+ temp / f"baseline_{index}",
+ timeout_s,
+ int(limits["max_certificate_bytes"]),
+ int(limits["memory_limit_mb"]),
+ int(limits["max_processes"]),
+ )
+ baseline_certificate = _parse_certificate(
+ baseline_run.certificate, workload, config
+ )
+ baseline_checked = _check_construction(
+ baseline_certificate, workload, config
+ )
+ workload_result["baseline"] = _construction_artifact(
+ baseline_certificate, baseline_checked, baseline_run
+ )
+ total_baseline_rotations += baseline_checked.rotations
+ total_baseline_cnots += baseline_checked.cnots
+ except Exception as exc:
+ message = str(exc) or type(exc).__name__
+ workload_result["baseline_error"] = message
+ workload_errors.append(f"baseline: {message}")
+ any_timeout = any_timeout or "timed out" in message.lower()
+
+ try:
+ candidate_run = _run_program(
+ candidate_executable,
+ workload,
+ temp / f"candidate_{index}",
+ timeout_s,
+ int(limits["max_certificate_bytes"]),
+ int(limits["memory_limit_mb"]),
+ int(limits["max_processes"]),
+ )
+ candidate_certificate = _parse_certificate(
+ candidate_run.certificate, workload, config
+ )
+ candidate_checked = _check_construction(
+ candidate_certificate, workload, config
+ )
+ workload_result["candidate"] = _construction_artifact(
+ candidate_certificate, candidate_checked, candidate_run
+ )
+ total_candidate_rotations += candidate_checked.rotations
+ total_candidate_cnots += candidate_checked.cnots
+ total_checked_entries += workload.dimension * workload.dimension
+ candidate_alpha_sum += candidate_checked.alpha
+ candidate_checked_scenarios += 1
+ except Exception as exc:
+ message = str(exc) or type(exc).__name__
+ workload_result["candidate_error"] = message
+ workload_errors.append(f"candidate: {message}")
+ any_timeout = any_timeout or "timed out" in message.lower()
+
+ if baseline_checked is not None and candidate_checked is not None:
+ try:
+ score = baseline_checked.objective / candidate_checked.objective
+ if not math.isfinite(score) or score <= 0.0:
+ raise EvaluationError(
+ "scenario score is non-positive or non-finite"
+ )
+ workload_result["score"] = score
+ scores.append(score)
+ except Exception as exc:
+ message = str(exc) or type(exc).__name__
+ workload_result["score_error"] = message
+ workload_errors.append(f"score: {message}")
+
+ if workload_errors:
+ workload_result["error"] = "; ".join(workload_errors)
+ failed_workloads.append(workload.workload_id)
+ failure_summaries.append(
+ f"{workload.workload_id}: {workload_result['error']}"
+ )
+ else:
+ workload_result["status"] = "ok"
+ results[workload.workload_id] = workload_result
+
+ partial_combined_score = (
+ math.exp(math.fsum(math.log(score) for score in scores) / len(scores))
+ if scores
+ else 0.0
+ )
+ all_workloads_valid = len(scores) == len(workloads)
+ runtime_s = time.perf_counter() - started
+ metrics = {
+ "combined_score": (
+ partial_combined_score if all_workloads_valid else 0.0
+ ),
+ "partial_combined_score": partial_combined_score,
+ "valid": 1.0 if all_workloads_valid else 0.0,
+ "timeout": 1.0 if any_timeout else 0.0,
+ "runtime_s": runtime_s,
+ "scenario_count": float(len(workloads)),
+ "successful_scenario_count": float(len(scores)),
+ "failed_scenario_count": float(len(workloads) - len(scores)),
+ "mean_score": math.fsum(scores) / len(scores) if scores else 0.0,
+ "min_score": min(scores) if scores else 0.0,
+ "baseline_total_rotations": float(total_baseline_rotations),
+ "candidate_total_rotations": float(total_candidate_rotations),
+ "baseline_total_cnots": float(total_baseline_cnots),
+ "candidate_total_cnots": float(total_candidate_cnots),
+ "candidate_mean_alpha": (
+ candidate_alpha_sum / candidate_checked_scenarios
+ if candidate_checked_scenarios
+ else 0.0
+ ),
+ "checked_matrix_entries": float(total_checked_entries),
+ }
+ artifacts["workloads"] = results
+ if failure_summaries:
+ artifacts["failed_workloads"] = failed_workloads
+ artifacts["failure_summary"] = "\n".join(failure_summaries)
+ artifacts["error_message"] = (
+ f"{len(failed_workloads)} of {len(workloads)} workloads failed; "
+ "see failure_summary and per-workload errors"
+ )
+ return metrics, artifacts
+ except Exception as exc:
+ message = str(exc)
+ artifacts["error_message"] = message
+ timed_out = "timed out" in message.lower()
+ return _invalid_metrics(time.perf_counter() - started, timeout=timed_out), artifacts
+
+
+def _write_json(path_text: str | None, payload: dict[str, Any]) -> None:
+ if not path_text:
+ return
+ path = Path(path_text).expanduser().resolve()
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text(
+ json.dumps(payload, indent=2, sort_keys=True, allow_nan=False) + "\n",
+ encoding="utf-8",
+ )
+
+
+def parse_args() -> argparse.Namespace:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("candidate", help="candidate C++ source")
+ parser.add_argument(
+ "--timeout-s",
+ type=float,
+ default=None,
+ help="optional per-workload execution timeout override",
+ )
+ parser.add_argument("--metrics-out", default=None)
+ parser.add_argument("--artifacts-out", default=None)
+ return parser.parse_args()
+
+
+def main() -> int:
+ args = parse_args()
+ timeout = None if args.timeout_s is None else max(0.1, float(args.timeout_s))
+ metrics, artifacts = evaluate(
+ Path(args.candidate).expanduser().resolve(), timeout_override_s=timeout
+ )
+ _write_json(args.metrics_out, metrics)
+ _write_json(args.artifacts_out, artifacts)
+ print(json.dumps(metrics, sort_keys=True, allow_nan=False))
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/verification/limited_exec.py b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/limited_exec.py
new file mode 100644
index 00000000..8c1c87cb
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/limited_exec.py
@@ -0,0 +1,59 @@
+"""Apply hard POSIX limits to this process, then exec a candidate program."""
+
+from __future__ import annotations
+
+import os
+import resource
+import sys
+
+
+def _positive_integer(text: str, label: str) -> int:
+ try:
+ value = int(text)
+ except ValueError as exc:
+ raise SystemExit(f"{label} must be an integer") from exc
+ if value <= 0:
+ raise SystemExit(f"{label} must be positive")
+ return value
+
+
+def main() -> int:
+ if len(sys.argv) < 8 or sys.argv[6] != "--":
+ raise SystemExit(
+ "usage: limited_exec.py MEMORY_MB CPU_SECONDS FILE_BYTES "
+ "MAX_PROCESSES CWD -- PROGRAM [ARG ...]"
+ )
+ memory_mb = _positive_integer(sys.argv[1], "MEMORY_MB")
+ cpu_seconds = _positive_integer(sys.argv[2], "CPU_SECONDS")
+ file_bytes = _positive_integer(sys.argv[3], "FILE_BYTES")
+ maximum_processes = _positive_integer(sys.argv[4], "MAX_PROCESSES")
+ working_directory = os.path.abspath(sys.argv[5])
+ program = os.path.abspath(sys.argv[7])
+ arguments = [program, *sys.argv[8:]]
+
+ # Session creation happens here, in a freshly spawned interpreter, so the
+ # multithreaded evaluator never needs a fork-time callback.
+ os.setsid()
+ os.chdir(working_directory)
+ memory_bytes = memory_mb * 1024 * 1024
+ resource.setrlimit(resource.RLIMIT_AS, (memory_bytes, memory_bytes))
+ resource.setrlimit(resource.RLIMIT_CPU, (cpu_seconds, cpu_seconds))
+ resource.setrlimit(resource.RLIMIT_FSIZE, (file_bytes, file_bytes))
+ resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
+ try:
+ resource.setrlimit(
+ resource.RLIMIT_NPROC, (maximum_processes, maximum_processes)
+ )
+ except (AttributeError, ValueError, OSError):
+ pass
+ try:
+ resource.setrlimit(resource.RLIMIT_NOFILE, (64, 64))
+ except (ValueError, OSError):
+ pass
+
+ os.execv(program, arguments)
+ raise AssertionError("unreachable") # pragma: no cover
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/verification/requirements.txt b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/requirements.txt
new file mode 100644
index 00000000..b7c72a67
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/requirements.txt
@@ -0,0 +1 @@
+# Standard library only.
diff --git a/benchmarks/QuantumComputing/KernelBlockEncoding/verification/test_evaluator.py b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/test_evaluator.py
new file mode 100644
index 00000000..d7c10711
--- /dev/null
+++ b/benchmarks/QuantumComputing/KernelBlockEncoding/verification/test_evaluator.py
@@ -0,0 +1,185 @@
+"""Focused standard-library tests for the kernel block-encoding evaluator."""
+
+from __future__ import annotations
+
+import math
+import tempfile
+import unittest
+from pathlib import Path
+
+import evaluator
+
+
+class KernelBlockEncodingTests(unittest.TestCase):
+ def test_integer_partial_hadamard_transform(self) -> None:
+ transformed, denominator = evaluator._basis_transform((1, 2, 3, 4), 2, 1)
+ self.assertEqual(transformed, [10, -2, -4, 0])
+ self.assertEqual(denominator, 2)
+
+ def test_identity_round_trip_and_error_rejection(self) -> None:
+ config = evaluator._validated_config()
+ scale = int(config["matrix_scale"])
+ angle_denominator = int(config["angle_denominator"])
+ workload = evaluator.Workload(
+ workload_id="identity_2",
+ dimension=2,
+ matrix_scale=scale,
+ epsilon_numerator=2,
+ matrix=(scale, 0, 0, scale),
+ input_bytes=b"test",
+ sha256="0" * 64,
+ )
+ entry_ticks = [0, angle_denominator, angle_denominator, 0]
+ coefficients = list(entry_ticks)
+ stride = 1
+ while stride < len(coefficients):
+ for base in range(0, len(coefficients), 2 * stride):
+ for offset in range(stride):
+ lhs = coefficients[base + offset]
+ rhs = coefficients[base + offset + stride]
+ coefficients[base + offset] = (lhs + rhs) // 2
+ coefficients[base + offset + stride] = (lhs - rhs) // 2
+ stride *= 2
+ gray_coefficients = tuple(
+ coefficients[evaluator._gray_code(index)]
+ for index in range(len(coefficients))
+ )
+ certificate = evaluator.Certificate(
+ basis_mask=0,
+ scale_numerator=scale,
+ angle_ticks=gray_coefficients,
+ sha256="1" * 64,
+ byte_count=1,
+ )
+ checked = evaluator._check_construction(certificate, workload, config)
+ self.assertLess(checked.error_upper_bound, workload.epsilon)
+ self.assertAlmostEqual(checked.alpha, 2.0)
+ self.assertEqual(checked.qubits, 3)
+
+ invalid = evaluator.Certificate(
+ basis_mask=0,
+ scale_numerator=scale,
+ angle_ticks=(0, 0, 0, 0),
+ sha256="2" * 64,
+ byte_count=1,
+ )
+ with self.assertRaises(evaluator.EvaluationError):
+ evaluator._check_construction(invalid, workload, config)
+
+ def test_walsh_gray_schedule_realizes_multiplexed_rotations(self) -> None:
+ entry_angles = [0.2, 0.8, 1.4, 2.2]
+ coefficients = list(entry_angles)
+ stride = 1
+ while stride < len(coefficients):
+ for base in range(0, len(coefficients), 2 * stride):
+ for offset in range(stride):
+ lhs = coefficients[base + offset]
+ rhs = coefficients[base + offset + stride]
+ coefficients[base + offset] = (lhs + rhs) / 2
+ coefficients[base + offset + stride] = (lhs - rhs) / 2
+ stride *= 2
+ gray_coefficients = [
+ coefficients[evaluator._gray_code(index)]
+ for index in range(len(coefficients))
+ ]
+
+ def multiply(
+ lhs: list[list[float]], rhs: list[list[float]]
+ ) -> list[list[float]]:
+ return [
+ [
+ sum(
+ lhs[row][inner] * rhs[inner][column]
+ for inner in range(2)
+ )
+ for column in range(2)
+ ]
+ for row in range(2)
+ ]
+
+ def rotation(angle: float) -> list[list[float]]:
+ cosine = math.cos(angle / 2)
+ sine = math.sin(angle / 2)
+ return [[cosine, -sine], [sine, cosine]]
+
+ identity = [[1.0, 0.0], [0.0, 1.0]]
+ bit_flip = [[0.0, 1.0], [1.0, 0.0]]
+ for control_state, expected_angle in enumerate(entry_angles):
+ realized = identity
+ for index, coefficient in enumerate(gray_coefficients):
+ realized = multiply(rotation(coefficient), realized)
+ transition_bit = (
+ 1
+ if index + 1 == len(gray_coefficients)
+ else (
+ evaluator._gray_code(index)
+ ^ evaluator._gray_code(index + 1)
+ ).bit_length()
+ - 1
+ )
+ if control_state & (1 << transition_bit):
+ realized = multiply(bit_flip, realized)
+ expected = rotation(expected_angle)
+ for row in range(2):
+ for column in range(2):
+ self.assertAlmostEqual(realized[row][column], expected[row][column])
+
+ def test_frozen_workload_hashes_and_source_shell(self) -> None:
+ config = evaluator._validated_config()
+ workloads = [
+ evaluator._build_workload(spec, int(config["matrix_scale"]))
+ for spec in config["workloads"]
+ ]
+ self.assertEqual(len(workloads), 6)
+ self.assertTrue(all(workload.sha256 for workload in workloads))
+ source = evaluator._validate_candidate_shell(
+ evaluator.TASK_DIR / "scripts" / "init.cpp",
+ int(config["limits"]["max_candidate_bytes"]),
+ )
+ self.assertEqual(source, evaluator.BASELINE_PATH.read_bytes())
+
+ def test_baseline_evaluates_to_valid_one(self) -> None:
+ metrics, artifacts = evaluator.evaluate(
+ evaluator.TASK_DIR / "scripts" / "init.cpp"
+ )
+ self.assertEqual(metrics["valid"], 1.0)
+ self.assertAlmostEqual(metrics["combined_score"], 1.0)
+ self.assertEqual(metrics["successful_scenario_count"], 6.0)
+ self.assertEqual(metrics["failed_scenario_count"], 0.0)
+ self.assertNotIn("failure_summary", artifacts)
+
+ def test_candidate_workload_failure_is_isolated(self) -> None:
+ source = (evaluator.TASK_DIR / "scripts" / "init.cpp").read_text(
+ encoding="utf-8"
+ )
+ function_start = "void optimize(Construction &construction) {\n"
+ injected_start = function_start + (
+ ' if (construction.workload_id() == "polynomial_gram_32")\n'
+ ' throw std::runtime_error("intentional isolated failure");\n'
+ )
+ self.assertIn(function_start, source)
+ source = source.replace(function_start, injected_start, 1)
+
+ with tempfile.TemporaryDirectory(prefix="kbe_isolation_test_") as temporary:
+ candidate = Path(temporary) / "candidate.cpp"
+ candidate.write_text(source, encoding="utf-8")
+ metrics, artifacts = evaluator.evaluate(candidate)
+
+ self.assertEqual(metrics["valid"], 0.0)
+ self.assertEqual(metrics["combined_score"], 0.0)
+ self.assertAlmostEqual(metrics["partial_combined_score"], 1.0)
+ self.assertEqual(metrics["successful_scenario_count"], 5.0)
+ self.assertEqual(metrics["failed_scenario_count"], 1.0)
+ self.assertEqual(
+ artifacts["failed_workloads"], ["polynomial_gram_32"]
+ )
+ failed = artifacts["workloads"]["polynomial_gram_32"]
+ self.assertIn("intentional isolated failure", failed["candidate_error"])
+ self.assertIn("candidate:", failed["error"])
+ self.assertAlmostEqual(
+ artifacts["workloads"]["multiscale_rbf_64"]["score"], 1.0
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/benchmarks/QuantumComputing/README.md b/benchmarks/QuantumComputing/README.md
index bddfb613..e1075a03 100644
--- a/benchmarks/QuantumComputing/README.md
+++ b/benchmarks/QuantumComputing/README.md
@@ -1,26 +1,31 @@
-# Agent-Evolve Quantum Optimization Tasks
+# Quantum Computing Benchmarks
-This folder contains three benchmark-driven optimization tasks based on this repository's `mqt.bench` APIs.
+This folder contains circuit construction, synthesis, routing, and cross-target
+optimization tasks.
-## Environment
-Use the requested interpreter:
+## Task list
-```bash
-pip install mqt.bench
-```
-
-## Task List
+- [`KernelBlockEncoding`](KernelBlockEncoding/): construct normalization- and
+ resource-efficient FABLE circuits for fixed-point QML kernel matrices. Its
+ evaluator is self-contained and CPU-only.
- `task_01_routing_qftentangled`: mapped-level routing optimization on IBM Falcon.
- `task_02_clifford_t_synthesis`: native-gates (`clifford+t`) synthesis optimization.
- `task_03_cross_target_qaoa`: one strategy evaluated on both IBM and IonQ targets.
-Current baseline strategies:
+The three historical `task_0*` benchmarks use this repository's `mqt.bench` APIs
+and require the configured quantum environment. `KernelBlockEncoding` uses only
+Python 3 and a C++17 compiler; it requires no quantum SDK or simulator.
+
+## Historical MQT task structure
+
+Current baseline strategies for the MQT-backed tasks:
+
- `task_01`: local rewrite preprocessing followed by target-aware multi-seed transpile search.
- `task_02`: `local rewrite -> clifford+t transpile(opt=3) -> local rewrite`.
- `task_03`: target-aware transpilation with backend-specific equivalence registration and transpile settings.
-## Unified Per-Task Structure
-Each task now uses the same structure:
+Each historical task uses the following structure:
+
- `baseline/solve.py`: evolve entrypoint with the task-specific baseline strategy.
- `baseline/structural_optimizer.py`: task-local local-rewrite helper reused by `solve.py`.
- `verification/evaluate.py`: single evaluation entrypoint that includes candidate and `opt0..opt3` references.
@@ -28,7 +33,16 @@ Each task now uses the same structure:
- `tests/case_*.json`: multiple differentiated test cases.
- `README*.md` and `TASK*.md`: run guide and task definition.
-## Eval
+## Evaluation
+
+Kernel block encoding:
+
+```bash
+.venvs/frontier-eval-driver/bin/python -m frontier_eval task=unified task.benchmark=QuantumComputing/KernelBlockEncoding algorithm=openevolve algorithm.iterations=0
+```
+
+MQT-backed tasks:
+
```bash
.venvs/frontier-eval-driver/bin/python -m frontier_eval task=unified task.benchmark=QuantumComputing/task_01_routing_qftentangled task.runtime.env_name=frontier-v1-main algorithm=openevolve algorithm.iterations=0
.venvs/frontier-eval-driver/bin/python -m frontier_eval task=unified task.benchmark=QuantumComputing/task_02_clifford_t_synthesis task.runtime.env_name=frontier-v1-main algorithm=openevolve algorithm.iterations=0
diff --git a/benchmarks/QuantumComputing/README_zh-CN.md b/benchmarks/QuantumComputing/README_zh-CN.md
index ff02ca4c..0e3a5386 100644
--- a/benchmarks/QuantumComputing/README_zh-CN.md
+++ b/benchmarks/QuantumComputing/README_zh-CN.md
@@ -1,26 +1,26 @@
-# Agent-Evolve 量子优化题目集
+# 量子计算基准
-本目录包含 3 个基于本仓库 `mqt.bench` API 构建的优化题目。
-
-## 环境
-请使用指定解释器:
-
-```bash
-pip install mqt.bench
-```
+本目录包含量子电路构造、综合、路由与跨目标优化任务。
## 题目列表
+
+- [`KernelBlockEncoding`](KernelBlockEncoding/):为定点 QML 核矩阵构造兼顾归一化与资源的 FABLE 电路;评测器自包含且仅使用 CPU。
- `task_01_routing_qftentangled`:面向 IBM Falcon 的 mapped-level 路由优化。
- `task_02_clifford_t_synthesis`:面向 `clifford+t` 原生门集的综合优化。
- `task_03_cross_target_qaoa`:同一策略在 IBM 与 IonQ 双目标上的鲁棒优化。
-当前 baseline 策略:
+三个历史 `task_0*` 任务使用本仓库的 `mqt.bench` API,需要已配置的量子环境。`KernelBlockEncoding` 只需 Python 3 与 C++17 编译器,不需量子 SDK 或模拟器。
+
+## 历史 MQT 任务结构
+
+MQT 任务的当前 baseline 策略:
+
- `task_01`:先做 local rewrite,再做面向 target 的多 seed transpile 搜索。
- `task_02`:`local rewrite -> clifford+t transpile(opt=3) -> local rewrite`。
- `task_03`:按后端注册 equivalence,并使用 target-aware transpile 参数。
-## 统一目录结构
-每个题目都采用同一结构:
+每个历史题目都采用以下结构:
+
- `baseline/solve.py`:包含各题目当前 baseline 策略的 evolve 入口。
- `baseline/structural_optimizer.py`:由 `solve.py` 复用的 task-local local-rewrite 辅助模块。
- `verification/evaluate.py`:单一评测入口,同时包含 candidate 与 `opt0..opt3` 参考对比。
@@ -29,6 +29,15 @@ pip install mqt.bench
- `README*.md` 与 `TASK*.md`:运行说明与任务定义。
## 评测命令
+
+核矩阵分块编码:
+
+```bash
+.venvs/frontier-eval-driver/bin/python -m frontier_eval task=unified task.benchmark=QuantumComputing/KernelBlockEncoding algorithm=openevolve algorithm.iterations=0
+```
+
+MQT 任务:
+
```bash
.venvs/frontier-eval-driver/bin/python -m frontier_eval task=unified task.benchmark=QuantumComputing/task_01_routing_qftentangled task.runtime.env_name=frontier-v1-main algorithm=openevolve algorithm.iterations=0
.venvs/frontier-eval-driver/bin/python -m frontier_eval task=unified task.benchmark=QuantumComputing/task_02_clifford_t_synthesis task.runtime.env_name=frontier-v1-main algorithm=openevolve algorithm.iterations=0