diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 434be51..d19ba4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,56 +7,27 @@ on: jobs: rust: runs-on: ubuntu-latest - # The Rust build compiles all of tensor4all-rs from source on a cold cache. timeout-minutes: 60 steps: - uses: actions/checkout@v4 - run: sudo apt-get update && sudo apt-get install -y libhdf5-dev liblapack-dev - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - - run: cargo test --release - - name: smoke elementwise + - run: cargo fmt --all -- --check + - run: cargo clippy --locked --all-targets -- -D warnings + - run: cargo test --release --locked + - name: smoke Fourier elementwise run: > BENCH_KS=4 BENCH_R=10 BENCH_RUNS=1 BENCH_WARMUPS=0 - OUT_DIR=/tmp/smoke EXPORT_HDF5=/tmp/smoke - cargo run --release --bin elementwise_fourier - - name: smoke mpo + OUT_DIR=/tmp/smoke/raw + cargo run --release --locked --bin elementwise_fourier + - name: smoke Gaussian elementwise run: > - BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 - OUT_DIR=/tmp/smoke EXPORT_HDF5=/tmp/smoke - cargo run --release --bin mpo_mpo_quantics - - name: smoke elementwise gauss2d + BENCH_NS=2 BENCH_RUNS=1 BENCH_WARMUPS=0 + BENCH_INPUT_CACHE_DIR=/tmp/smoke-cache OUT_DIR=/tmp/smoke/raw + cargo run --release --locked --bin elementwise_gauss2d_patched + - name: smoke Gaussian MPO contraction using the shared cache run: > - BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 - OUT_DIR=/tmp/smoke EXPORT_HDF5=/tmp/smoke-gauss2d - cargo run --release --bin elementwise_gauss2d - - name: smoke elementwise gauss2d scaling - # No EXPORT_HDF5: case 4 exports no instances, so there is no Julia - # check for it, and a single N is enough to exercise the runner. - run: > - BENCH_NS=8 BENCH_R0=8 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 - OUT_DIR=/tmp/smoke - cargo run --release --bin elementwise_gauss2d_scaling - - name: smoke elementwise gauss2d patched - # Both instance families, since they share only the harness: the default - # aniso one, whose N = 8 point is a fraction of a second, and the smooth - # one with R0 lowered so the patched construction stays cheap there, since - # at the default R0 one N already builds hundreds of patches. No - # EXPORT_HDF5, as for case 4. - run: > - BENCH_NS=8 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 - OUT_DIR=/tmp/smoke - cargo run --release --bin elementwise_gauss2d_patched - && - BENCH_FAMILY=smooth BENCH_NS=8 BENCH_R0=8 BENCH_RUNS=1 BENCH_WARMUPS=0 - BENCH_SANITY=1e-1 OUT_DIR=/tmp/smoke - cargo run --release --bin elementwise_gauss2d_patched - - uses: julia-actions/setup-julia@v2 - with: - version: "1" - - name: julia checks - run: | - julia --project=julia -e 'using Pkg; Pkg.instantiate()' - julia --project=julia julia/check_elementwise.jl /tmp/smoke 4 - julia --project=julia julia/check_mpo_mpo.jl /tmp/smoke 8 - julia --project=julia julia/check_elementwise_gauss2d.jl /tmp/smoke-gauss2d 8 + BENCH_NS=2 BENCH_RUNS=1 BENCH_WARMUPS=0 + BENCH_INPUT_CACHE_DIR=/tmp/smoke-cache OUT_DIR=/tmp/smoke/raw + cargo run --release --locked --bin mpo_mpo_aniso_patched diff --git a/.gitignore b/.gitignore index 3b49edf..087dcc3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ Cargo.lock.orig __pycache__/ .venv/ -julia/Manifest.toml result/**/raw/*.h5 diff --git a/AGENTS.md b/AGENTS.md index 71da985..3ed4e43 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,66 +1,35 @@ # Agent guidance -Read `README.md` first for the cases, arm names and environment knobs. This file -covers only what is easy to get wrong. - -## Julia is JIT compiled - -Any TIMED comparison against Julia must run warmup iterations before it measures. -A first invocation includes compilation time and is not a measurement. - -The scripts in `julia/` are correctness checks only, not benchmarks. They read an -exported HDF5 instance back through ITensors.jl and compare against the same -analytic formula the Rust side uses. Their wall time is dominated by compilation -and must never be quoted as a timing result. A real Julia timing arm would need -its own warmup loop and a stated count, as `BENCH_WARMUPS` does in Rust. - -## Runners are self checking - -Every runner exits nonzero when any arm's error exceeds its sanity gate, so a -green exit is part of the evidence that a change is sound. The gates screen order -unity wrongness, not precision. The one exception is the `zipup_treetn` arm of -cases 3 and 4, gated at a hardcoded `5.0` because its error at the fixed output -budget is genuinely of order one (README known issue 8), so for that arm the -gate catches only a non-finite result or a runaway magnitude. Never loosen one -silently to make a run pass. - -## Results are committed deliberately - -Files under `result//` are generated by `scripts/run_all.sh ` -and committed on purpose, as the record of a full sweep on a stated machine. Do -not hand edit them, and do not regenerate them as a side effect of an unrelated -change. Use `OUT_DIR=/tmp/...` for probe runs. One profile belongs to one -physical machine, named after the machine, and a sweep from a different machine -goes to its own profile instead of overwriting another machine's numbers: wall -times of the memory heavy arms differ by factors between machines (README known -issue 10). Never put a hostname in a result file, the machine label and the -hardware fields in `run.yaml` carry the identity. - -## Expensive benchmark inputs are cached - -Every runner with nontrivial deterministic input construction must cache that -input and reuse it across algorithm comparisons and reruns. Input generation, -cache loading, format conversion and patch preparation stay outside timed -regions. - -- Use one shared ignored cache directory, `.cache/inputs/` by default. -- Include every input-defining parameter, seed and an explicit input schema - version in the cache key. Bump the schema when generation semantics change. -- Write cache entries atomically and treat an existing entry as immutable. -- Validate loaded shapes, ranks, dtypes and shared index identities before use. -- Record the cache key, hit or miss, load time and build time in each result. -- Provide explicit refresh and cache-directory environment knobs. Never silently - accept a corrupt or incompatible entry. -- Cache inputs only, never algorithm outputs or timed intermediates. -- Tests whose subject is input generation or serialization must force a rebuild; - ordinary unit tests remain isolated and must not depend on persistent cache - state. - -## Upstream is pinned - -`Cargo.toml` pins every `tensor4all-rs` crate to one `rev`. Bump it deliberately, -move all the crates together, and never mix backend features across them. A bump -can change measured numbers, so it belongs in its own commit with a rerun. +Read `README.md` before changing case definitions, timing boundaries, input generation, or environment settings. + +## Maintained scope + +The repository has exactly three benchmark cases: Fourier elementwise, Gaussian elementwise global versus patched, and Gaussian MPO-MPO contraction global versus patched. Do not add another case when an arm or metric in one of these cases answers the question. + +Gaussian inputs use independent two-dimensional interpolative decomposition per term, deterministic balanced pairwise add-and-compress, final relative-L2/SVD tolerance `1e-6`, and fixed patch cap 128. Do not add TCI generation, whole-mixture interpolation, isotropic controls, independent `R` sweeps, or a runtime patch-cap knob without an explicit design change. + +ACI residual tolerance is not an L2 tolerance. Keep its internal metric explicit and compare it with other arms only through the common achieved external error. + +## Timing + +Time only the benchmarked elementwise or contraction operation. Input construction, cache I/O, compression, conversion, patch preparation, output conversion, and accuracy evaluation stay outside timed regions. + +Run release builds with one pinned CPU core and single-threaded Rayon and BLAS. Warm up any JIT-compiled external implementation before timing it. + +## Results + +Files under `result//` are generated by `scripts/run_all.sh ` and committed deliberately. Do not edit them manually. Probe runs belong under `/tmp`. One profile belongs to one physical machine and contains no hostname. + +## Input cache + +Every expensive deterministic input must use the shared ignored `.cache/inputs/` directory by default. + +- Include every content-defining parameter, seed, upstream revision, and schema version in the key. +- Write atomically and treat existing entries as immutable. +- Validate loaded length, site dimensions, scalar type, and index compatibility. +- Record key, hit or miss, load time, and build time. +- Cache inputs only, never timed outputs. +- Input-generation and serialization tests must force a rebuild. ## Pushing @@ -76,7 +45,10 @@ together with the hardware behind them. Keep hostnames out of the description as well as out of the files: on a public repository a hostname leaks the operator's institution and location over time. -## Prose style +## Upstream + +All tensor4all-rs crates are pinned to one revision in `Cargo.toml`. Move every pin together. A pin change requires fresh measurements. + +## Prose -No em dashes or en dashes anywhere in this repository's documents, comments or -generated reports. Use commas, colons or separate sentences. +Do not use em dashes or en dashes in documentation, comments, or generated reports. diff --git a/Cargo.lock b/Cargo.lock index f0da780..47e3678 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1013,14 +1013,6 @@ dependencies = [ "pulp", ] -[[package]] -name = "quanticsgrids" -version = "0.2.0" -source = "git+https://github.com/tensor4all/quanticsgrids-rs?rev=8214b72#8214b72aef2cc42167226c0b8e43ef14eba44a6f" -dependencies = [ - "thiserror 2.0.20", -] - [[package]] name = "quote" version = "1.0.47" @@ -1373,7 +1365,6 @@ dependencies = [ "tensor4all-itensorlike", "tensor4all-partitionedtreetn", "tensor4all-partitionedtt", - "tensor4all-quanticstci", "tensor4all-simplett", "tensor4all-treetn", ] @@ -1639,24 +1630,6 @@ dependencies = [ "thiserror 2.0.20", ] -[[package]] -name = "tensor4all-quanticstci" -version = "0.2.0" -source = "git+https://github.com/tensor4all/tensor4all-rs?rev=9e9aedaebe0d3918b34dd399ff0981e337f3835b#9e9aedaebe0d3918b34dd399ff0981e337f3835b" -dependencies = [ - "anyhow", - "num-complex", - "num-traits", - "quanticsgrids", - "rand", - "tensor4all-core", - "tensor4all-simplett", - "tensor4all-tensorbackend", - "tensor4all-treetci", - "tensor4all-treetn", - "thiserror 2.0.20", -] - [[package]] name = "tensor4all-simplett" version = "0.2.0" @@ -1709,23 +1682,6 @@ dependencies = [ "thiserror 2.0.20", ] -[[package]] -name = "tensor4all-treetci" -version = "0.2.0" -source = "git+https://github.com/tensor4all/tensor4all-rs?rev=9e9aedaebe0d3918b34dd399ff0981e337f3835b#9e9aedaebe0d3918b34dd399ff0981e337f3835b" -dependencies = [ - "anyhow", - "num-complex", - "petgraph", - "rand", - "tenferro-linalg", - "tenferro-tensor", - "tensor4all-core", - "tensor4all-tensorbackend", - "tensor4all-treetn", - "thiserror 2.0.20", -] - [[package]] name = "tensor4all-treetn" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 47b00dd..1b463b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ tensor4all-treetn = { git = "https://github.com/tensor4all/tensor4all-rs", rev = tensor4all-itensorlike = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-itensorlike" } tensor4all-partitionedtt = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-partitionedtt" } tensor4all-partitionedtreetn = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-partitionedtreetn" } -tensor4all-quanticstci = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-quanticstci" } tensor4all-interpolativeqtt = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-interpolativeqtt" } tensor4all-hdf5 = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-hdf5" } tensor4all-core = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "9e9aedaebe0d3918b34dd399ff0981e337f3835b", package = "tensor4all-core" } diff --git a/README.md b/README.md index b73dd68..fd6ce3e 100644 --- a/README.md +++ b/README.md @@ -1,1033 +1,84 @@ # tensor4all-benchmark -An open experimentation ground for comparing tensor network contraction algorithms in -[tensor4all-rs](https://github.com/tensor4all/tensor4all-rs) on reproducible problem -instances. Every input is generated in Rust from a fixed seed, every run is recorded as a -JSON `RunRecord` (timings, accuracy, bond dimensions), and the reports are rendered from -those records, so a result can always be traced back to the instance and the upstream -revision that produced it. The pinned `tensor4all-rs` revision lives in `Cargo.toml`. +Reproducible benchmarks for tensor network algorithms in [tensor4all-rs](https://github.com/tensor4all/tensor4all-rs). Inputs use fixed seeds, timed regions exclude preparation, every arm writes JSON, and reports are generated from those records. -## Cases at a glance +## Maintained cases -| Case | What it measures | Details | Runner | Latest report | Plots | -| --- | --- | --- | --- | --- | --- | -| 1. `elementwise_fourier` | Elementwise product of two 1D quantics Fourier series, swept over the mode count `K`, against the exact product series | [description](#case-1-elementwise-hadamard-product-of-quantics-tensor-trains) | [`src/bin/elementwise_fourier.rs`](src/bin/elementwise_fourier.rs) | [`result/mac-cpu/elementwise_fourier.md`](result/mac-cpu/elementwise_fourier.md) | [time](result/mac-cpu/elementwise_fourier-time.svg), [error](result/mac-cpu/elementwise_fourier-error.svg) | -| 2. `mpo_mpo_quantics` | Contraction of two 2D quantics Gaussian-mixture MPOs over their shared variable, swept over bits per variable `R`, against the closed-form Gaussian integral | [description](#case-2-mpo-mpo-contraction-of-2d-quantics-gaussian-mixtures) | [`src/bin/mpo_mpo_quantics.rs`](src/bin/mpo_mpo_quantics.rs) | [`result/mac-cpu/mpo_mpo_quantics.md`](result/mac-cpu/mpo_mpo_quantics.md) | [time](result/mac-cpu/mpo_mpo_quantics-time.svg), [error](result/mac-cpu/mpo_mpo_quantics-error.svg) | -| 3. `elementwise_gauss2d` | Elementwise product of two 2D quantics Gaussian mixtures at a fixed output budget, swept over bits per variable `R`, against the exact pointwise product | [description](#case-3-elementwise-product-of-2d-quantics-gaussian-mixtures) | [`src/bin/elementwise_gauss2d.rs`](src/bin/elementwise_gauss2d.rs) | [`result/mac-cpu/elementwise_gauss2d.md`](result/mac-cpu/elementwise_gauss2d.md) | [time](result/mac-cpu/elementwise_gauss2d-time.svg), [error](result/mac-cpu/elementwise_gauss2d-error.svg) | -| 4. `elementwise_gauss2d_scaling` | Density-constant scaling study of case 3: how the quantics input rank `chi_in` grows with the number of Gaussians `N` when the box area grows proportionally to `N` | [description](#case-4-density-constant-scaling-of-the-quantics-rank) | [`src/bin/elementwise_gauss2d_scaling.rs`](src/bin/elementwise_gauss2d_scaling.rs) | [`result/mac-cpu/elementwise_gauss2d_scaling.md`](result/mac-cpu/elementwise_gauss2d_scaling.md) | [chi](result/mac-cpu/elementwise_gauss2d_scaling-chi.svg), [time](result/mac-cpu/elementwise_gauss2d_scaling-time.svg), [error](result/mac-cpu/elementwise_gauss2d_scaling-error.svg) | -| 5. `elementwise_gauss2d_patched` | Patched (domain decomposed) elementwise product, controlled by a global relative tolerance instead of a fixed output budget, comparing patched and global representations at equal accuracy on size and time, over two instance families: anisotropic narrow spikes by default and case 4's smooth Gaussians on request | [description](#case-5-patched-elementwise-product-at-equal-accuracy) | [`src/bin/elementwise_gauss2d_patched.rs`](src/bin/elementwise_gauss2d_patched.rs) | [`result/mac-cpu/elementwise_gauss2d_patched.md`](result/mac-cpu/elementwise_gauss2d_patched.md) | [time](result/mac-cpu/elementwise_gauss2d_patched-time.svg), [error](result/mac-cpu/elementwise_gauss2d_patched-error.svg), [parameters](result/mac-cpu/elementwise_gauss2d_patched-params-aniso.svg) | -| 6. `mpo_mpo_aniso_patched` | Fit contraction of anisotropic Gaussian MPOs, comparing the global baseline with patched chain TreeTN | [description](#case-6-patched-mpo-mpo-fit-contraction) | [`src/bin/mpo_mpo_aniso_patched.rs`](src/bin/mpo_mpo_aniso_patched.rs) | [contraction](result/linux-epyc-7713p/mpo_mpo_aniso_patched.md), [input scaling](result/linux-epyc-7713p/mpo_mpo_aniso_input_scaling.md) | [crossover](result/linux-epyc-7713p/mpo_mpo_aniso_patched.md#results), [patch scaling](result/linux-epyc-7713p/mpo_mpo_aniso_input_scaling.md#results) | - -## Benchmark cases - -### Case 1: elementwise (Hadamard) product of quantics tensor trains - -Two random Fourier series of `K+1` modes each are built as exact rank-`(K+1)` QTTs on `R` -bits, SVD-compressed to the working tolerance, and multiplied elementwise. The exact -product series is known analytically (a Fourier series of `2K+1` modes), so accuracy is -measured pointwise against it rather than against another tensor network. The setup -follows the elementwise product benchmark of arXiv:2604.00037. Algorithms: `naive` -(full product then truncate), `zipup` (single-pass zip-up truncation), `fit` -(variational sweeps), `aci` (adaptive cross interpolation). -Runner: [`src/bin/elementwise_fourier.rs`](src/bin/elementwise_fourier.rs), sweep over `K`. - -### Case 2: MPO-MPO contraction of 2D quantics Gaussian mixtures - -Two random mixtures of `n` isotropic 2D Gaussians are represented as quantics MPOs on -`R` bits per variable over the box `[-L, L]^2`, with `x` as the row index and `y` as the -column index. Contracting the two MPOs over `y` and scaling by the grid spacing -approximates the integral `int dy f(x, y) g(y, z)`, which has a closed-form Gaussian -answer, so again the reference is analytic. Algorithms: `naive` (simplett), -`zipup_simplett`, `zipup_treetn`, `fit_treetn`. Where both upstream engines implement an -algorithm, both are benchmarked as separate arms, so the engine is a visible variable -rather than a hidden one; the two zipup arms are the same algorithm on the two engines and -their difference isolates the engine. Each record carries the engine that ran it as -`engine`. The one missing pair is simplett fit, excluded because its variational update is -a stub upstream (known issue 1). -The contraction output bond dimension is pinned to the input rank, and the rank cap is the -only thing that decides it: every algorithm runs with its maximum bond dimension capped at -`chi_in`, the larger of the two input MPO ranks, and with a truncation tolerance pinned -inert, so all arms are compared at the same output budget and each one genuinely exhausts -it unless its exact rank is smaller. `BENCH_TOL` therefore scopes only the input TCI -construction, where it fixes `chi_in` and thus the instance, while `BENCH_CONTRACT_TOL`, -default `1e-15`, is what the arms receive and is recorded as `contract_tol` in the params of -every record. This removes the ambiguity of which constraint binds: without it a -tolerance-driven arm could stop early and report a `chi_out` below the budget, so the error -column would compare arms at different effective ranks. `BENCH_MAX_BOND` also caps only the -input TCI construction. As measured over the default sweep `R` = 6, 8, 10, 12 and 14 with -the pinned revision, `naive` and `fit_treetn` land on the same error, `5.7e-10` to -`3.5e-9`, and the two zipup arms, -`zipup_simplett` and `zipup_treetn`, agree with each other to the last reported digit and -sit four to five orders of magnitude higher, `2.1e-5` to `1.1e-4`. Every arm returns -`chi_out` equal to the budget. The split is therefore algorithmic rather than engine-driven: -single-pass zip-up truncation is what costs accuracy, and both engines running it produce -the same answer. What zip-up buys is speed, since it is the fastest arm at every `R` and -stays between 0.009 s and 0.25 s, while `naive` grows steeply (1.1 s at `R` = 8, 32 s at -`R` = 10, 89 to 91 s at `R` = 12 and 14) because it forms the full -contracted bond before truncating; at `R` >= 10 that arm's intermediates are large enough -that its wall time tracks the machine and the ambient memory pressure rather than the -algorithm alone, so it is not comparable across profiles (known issue 10). -`fit_treetn` reaches naive accuracy at a fraction of the -naive cost, under 0.8 s at every `R`. -Runner: [`src/bin/mpo_mpo_quantics.rs`](src/bin/mpo_mpo_quantics.rs), sweep over `R`. - -### Case 3: elementwise product of 2D quantics Gaussian mixtures - -Two independent random mixtures of `n` isotropic 2D Gaussians are cross-interpolated into -fused 2D quantics tensor trains on the box `[-L, L)^2`, `R` sites of site dimension 4 whose -local index is `x_bit + 2 * y_bit` with the most significant bit first. The benchmarked -operation is the elementwise product `h = f * g` on the `2^R` by `2^R` grid. The reference -is exact and pointwise, `h(x, y) = f(x, y) * g(x, y)`, with no quadrature and no tail, so -unlike case 2 this case has no reference error floor of its own. Algorithms: `naive` -(core-wise bond Kronecker product then an SVD sweep, written in this repository on simplett -primitives, recorded with `engine` = `local`), `zipup_treetn` and `fit_treetn` (both -`tensor4all_treetn::hadamard`, `engine` = `treetn`), and `aci` -(`tensor4all_aci::elementwise`, adaptive cross interpolation of the pointwise product, -`engine` = `aci`). There is no simplett arm, because simplett exposes no elementwise product -for tensor trains at the pinned revision (known issue 7), so unlike case 2 this case cannot -compare two engines on one algorithm. -Like case 2, the output bond dimension is pinned to the input rank and the rank cap alone -decides it: every algorithm runs capped at `chi_in`, the larger of the two input ranks, with -the truncation tolerance pinned inert at `BENCH_CONTRACT_TOL`, default `1e-15`, and recorded -as `contract_tol`. `BENCH_TOL` scopes only the input TCI construction, where it fixes -`chi_in` and the instance, as does `BENCH_MAX_BOND`. All arms are therefore compared at the -same output budget, each one exhausts it unless its exact rank is smaller, and the error is -the discriminator. The `aci` arm additionally runs with `scale_tolerance` enabled, recorded -as `aci_scale_tolerance`, so that its pivot criterion is scale-relative and equally -unreachable and the cap is what decides for it too. As measured over the default sweep -`R` = 6, 8, 10, 12 and 14 with the pinned revision (`chi_in` of 53 and then 76 to 80 once -the quantics rank saturates), `naive`, `fit_treetn` and `aci` agree to the last -reported digit or close to it, from `3.6e-11` at `R` = 6 to about `1.5e-8` at `R` = 10, all -at the full `chi_out`. `zipup_treetn` -collapses: it spends the same budget and returns `1.3e-1` to `1.1` across the sweep, an -answer with no -correct digits, and that number swings by a factor of two between runs of the same -configuration, so read it as order one rather than as a measurement. The separation is much -sharper than in case 2, where the same single-pass -truncation cost only four to five orders of magnitude, because the exact elementwise -product has rank up to `chi_in` squared and a budget of `chi_in` discards nearly all of it, -while naive and fit find a near-optimal basis for the same budget. Raising the budget -recovers zipup smoothly, to `1.8e-7` at 8 `chi_in` and `3.9e-8` unconstrained, so this is -the price of the fixed budget rather than a broken arm (known issue 8). On cost, `naive` is -again the expensive one, forming the full `chi_in`-squared bond before truncating: 0.05 s at -`R` = 6, 3.9 s at `R` = 8 and 6 to 7.6 s at `R` = 10 to 14, against 1.1 s for `fit_treetn` -and 0.35 s for `zipup_treetn` at `R` = 14. `aci` is the cheapest arm at every point of the -sweep, 1 ms at `R` = 6 rising only to 61 ms at `R` = 14, six to -fourteen times below `zipup_treetn`, because the pinned revision carries its early exit on -rank saturation from -[tensor4all-rs#591](https://github.com/tensor4all/tensor4all-rs/pull/591), so its sweep stops -once the pivots stop improving instead of running to its iteration limit under the unreachable -stopping criterion. - -One pitfall is worth naming, because the metric hides it. The relative error is normalized -by the largest sampled `|f * g|`, and `f` and `g` are drawn independently, so if the -Gaussians are made too narrow (a high `BENCH_ALPHA_HI`) or the density too low, the two -mixtures stop overlapping, the product is numerically zero everywhere on the grid, and the -normalization collapses exponentially while the error it divides stays finite. The reported -number would then be noise dressed as an accuracy. Both runners therefore measure, over the -same sampled points the error uses, the reference scale `ref_scale` = max `|f * g|` and the -input scales `input_scale_f` and `input_scale_g`, and refuse to benchmark the instance -before any timing if `ref_scale` falls below `1e-6 * input_scale_f * input_scale_g`, with a -message pointing at `BENCH_ALPHA_HI` and at the density. All three scales are recorded in -the params of every case-3 and case-4 record, so the health of an instance can be checked -after the fact. The default instances are nowhere near the guard: `ref_scale` is `5.3e-1` -against input scales of `1.2` and `0.87` at `R` = 6, a ratio of `0.49`, roughly five orders -of magnitude above the threshold. - -Runner: [`src/bin/elementwise_gauss2d.rs`](src/bin/elementwise_gauss2d.rs), sweep over `R`. - -### Case 4: density-constant scaling of the quantics rank - -Case 3 holds the mixture fixed and sweeps the bit count, so its `chi_in` saturates and says -nothing about how hard a bigger problem is. Case 4 asks the complementary question: how does -the quantics input rank `chi_in` of a 2D Gaussian mixture grow with the number of Gaussians -`N` when the DENSITY of Gaussians is held constant? Two hypotheses are worth separating, -`chi ~ sqrt(N)`, which is what a boundary-law or one-dimensional-cut picture predicts for a -fused 2D quantics train, and `chi ~ N`, which is what a naive sum-of-terms picture predicts. - -The construction keeps two things fixed while `N` grows. Density first: the box half-width -is `L = L0 * sqrt(N / N0)`, so the box area `(2L)^2` grows proportionally to `N` and the -number of Gaussians per unit area is the same at every point of the sweep. Resolution -second: growing the box at a fixed bit count would coarsen the grid and under-resolve each -Gaussian, which would confound rank growth with a loss of resolution, so the bit count grows -with the box as `R = R0 + round(log2(L / L0))`, one extra bit per doubling of `L`. That keeps -the grid spacing `2L / 2^R` roughly constant, so every Gaussian is resolved by roughly the -same number of grid points at every `N`. Because `R` moves in integer steps while `L` moves -continuously, the spacing is constant only up to a factor of at most `sqrt(2)`. The defaults -`L0` = 6.0, `N0` = 8, `R0` = 10 make `N` = 8 exactly the case-3 instance. - -Everything else mirrors case 3: two independent mixtures, fused 2D quantics trains, and the -elementwise product `h = f * g` at the fixed output budget `chi_out <= chi_in`, decided by -the rank cap alone with the truncation tolerance pinned inert at `BENCH_CONTRACT_TOL` and the -`aci` arm running scale-relative, judged by the -sampled max relative error against the exact pointwise product. The arms are `zipup_treetn`, -`fit_treetn` and `aci` only. The case-3 `naive` arm is excluded from the defaults: it forms -the full `chi_in`-squared bond before truncating, and this case deliberately pushes `chi_in` -to roughly twice the case-3 value, where that arm would dominate the wall time of the whole -sweep without adding a separate conclusion, since it tracks `fit_treetn` to the last reported -digit in case 3. Pass it through `BENCH_ALGOS` if you want it. The overlap guard of case 3 -applies here unchanged, and matters more, since the box grows with `N`: the runner records -`ref_scale`, `input_scale_f` and `input_scale_g` and refuses a degenerate instance before -timing. At the default `N` = 8 point `ref_scale` is `4.6e-1` against input scales of `1.0` -and `0.85`, a ratio of `0.54`. - -As measured over the default sweep `N` = 8, 16, 32, 64 with the pinned revision, `chi_in` is -78, 103, 117 and 145 at `L` = 6.000, 8.485, 12.000 and 16.971 and `R` = 10, 11, 11 and 12. A -least-squares fit of `log(chi_in)` against `log(N)` gives `chi_in ~ N^0.29`, so over this -range the growth is sublinear by a wide margin and even slower than `sqrt(N)`: an eightfold -increase in the number of Gaussians costs less than a doubling of the rank. The linear -hypothesis is comfortably excluded, and the `sqrt(N)` hypothesis is the closer of the two -without being reached, which is consistent with `sqrt(N)` acting as an upper bound that -finite-size effects have not yet saturated. Read the exponent as a measurement over a factor -of 8 in `N` on one seed rather than as an asymptotic law. It is robust against the quantics -construction wobble of known issue 5: perturbing all four `chi_in` values by plus or minus 2 -moves the fitted slope only within 0.27 to 0.31, and independent reruns that landed on -`chi_in` of 77, 103, 117, 141 and on 79, 104, 117, 143 fit to 0.28 and 0.27. The scaling conclusion is untouched by the -`chi_out`-driven change, since `chi_in` comes from the input TCI construction, which -`BENCH_CONTRACT_TOL` does not reach. On the arms themselves the case-3 -verdict survives at twice the rank. Measured at `N` = 8 and 16, `fit_treetn` and `aci` agree -at about `1.3e-8` and `1.0e-8` while `zipup_treetn` returns `1.9e-1` and `3.5e-1`, all three at -the full `chi_out` of 78 and 103. Across the whole sweep that arm stays of order one, between -`1.7e-1` and `5.7e-1`, with no monotone trend in `N`, so the budget costs it every correct -digit at any rank in this range. `aci` is the cheap arm here too, eight to twelve -times below `zipup_treetn` -and more than an order of magnitude below `fit_treetn`: 0.03 s at `N` = 8 and 0.08 s at `N` = 16, -against 0.8 s and 2.1 s for `fit_treetn`, since the pinned revision stops its sweep once the -pivots saturate. Everything quoted above comes from the committed `mac-cpu` sweep. -Runner: [`src/bin/elementwise_gauss2d_scaling.rs`](src/bin/elementwise_gauss2d_scaling.rs), -sweep over `N`. - -### Case 5: patched elementwise product at equal accuracy - -Cases 3 and 4 both form one global tensor train for each input and one for the product, so -their rank is set by the hardest region of the box, and their comparison is made at a fixed -output budget. Case 5 changes both of those, and it runs on two instance families rather than -one. The representation becomes patched: each input -is a `PartitionedTT` from `tensor4all-partitionedtt`, a set of tensor trains over disjoint -subdomains, where a subdomain is a set of quantics digits held fixed. Fixing the leading fused -site picks one quadrant of the box, fixing the next one a sub-quadrant, so patches are regions -of the box rather than arbitrary slices: a contiguous quadrant when the digits fixed are the -leading ones, and a periodic union of them when they are not. The stopping rule is the -per-patch rank cap `BENCH_PATCH_MAX_BOND`: split until every patch fits under it. A hard region of the box therefore costs patches rather -than global rank. - -Instance families, `BENCH_FAMILY`. The default is `aniso`: `N` anisotropic narrow spikes, of a -fixed minor width `BENCH_ANISO_SIGMA` = 0.05, each one stretched by its own aspect ratio, drawn -log-uniform in `[1, BENCH_ANISO_RHO_MAX]` = `[1, 8]`, along its own orientation, drawn uniform -in `[0, pi)`. Weights are `U[0.5, 1.5]` and centers uniform in nine tenths of the box, and the -draw order per spike is weight, aspect, orientation, center. The mean spacing between spikes is -held at `BENCH_ANISO_SPACING` = 3 minor widths, so `N` spikes fill a box of half-width -`L = 3 sigma sqrt(N) / 2`, and `R` is the smallest bit count whose grid step resolves the minor -width to a quarter, `2L / 2^R <= sigma / 4`. Fixing the ratio of spacing to width is what keeps -the elementwise product non degenerate as `N` grows: two independent draws overlap by a -constant fraction at every `N`. Over the default sweep the sampled `ref_scale` sits between -0.38 and 0.83 of `max|f| max|g|`, six orders of magnitude above the guard described above, with -no trend in `N`. The other family, -`smooth`, is case 4's and is unchanged: isotropic Gaussians of log-uniform inverse width at -constant density, `L = L0 sqrt(N / N0)` and `R = R0 + round(log2(L / L0))`, so the two cases can -still be read against each other point for point. - -The default is `aniso` because the smooth family gives the patching nothing to isolate. A -smooth 2D mixture at constant density is easy everywhere, so subdividing it only pays the -per-patch overhead, which is what the case-5 verdict on it says. Narrow spikes at a fixed -spacing-to-width ratio are the opposite: the function is a field of small hard features whose -global rank climbs through the sweep while a patched representation is held at its per-patch -cap by construction. This is a contest of ranks rather than a wall: the geometric bound -`4^(R/2)` of the bit count grows like `sqrt(N)` as the resolution rule raises `R` with the -box, and the measured global rank does not even follow that, it decelerates toward a -density-set plateau. The global representation never runs out of room, it pays a bounded -but large rank where the patched one pays patch count. Measured single-threaded -at the pinned revision and `rtol` = 1e-8, the global input rank `chi_in` of the aniso -family is - -| `N` | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | -|---|---|---|---|---|---|---|---|---| -| `R` | 6 | 6 | 7 | 7 | 8 | 8 | 9 | 9 | -| `chi_in`, aniso | 45 | 53 | 64 | 64 | 89 | 120 | 185 | 256 | -| `chi_in`, isotropic control | 49 | | | 64 | 94 | 126 | 196 | 256 | - -which grows like `N^0.5` over the middle of the range, `N` = 64 to 512, and then decelerates -toward saturation: 256 at `N` = 1024 and 2048 and 289 at 4096, each verified converged (the -TCI reaches the tolerance in 4 to 6 of its 200 allowed iterations, and raising the -resolution rule from sigma/4 to sigma/16, hence `R` by two bits and the geometric bound to -4096, leaves the ranks unchanged). That the `N` = 1024 value equals the `R` = 9 bound is a -coincidence, not censoring. The saturation is what statistical homogeneity predicts: at -constant density a larger box adds more of the same landscape, so the local structure -diversity that sets the maximal bond is fixed by the density and the tolerance rather than -by `N`. The first row up to -`N` = 512 is the default sweep, the `N` = 1024 column and the second row are separate probe runs -at the same settings; a rank here moves by a unit or two between two constructions of the same -instance, since the input TCI is not bit-reproducible (88 against 89 at `N` = 128, 182 against -185 at 512 in two runs). The smooth family for -comparison grows like `N^0.33` over its own sweep (case 4's measurement), and its `R` grows -with the box, so it reaches a rank of 142 at `N` = 64 on a much finer grid. - -The last row of that table is the control, `BENCH_ANISO_RHO_MAX=1`, which draws circular -spikes of one common shape and leaves everything else alone. It grows the same way. So at this -spacing-to-width ratio the rank comes from the density of narrow features and not from the -anisotropy, which is worth recording because the opposite is easy to assume: a family of one -common shape is a pure shift family, a low dimensional manifold, and one expects a quantics -TCI to exploit it. At `R` = 8 and up it does not, or not enough to matter. The per-spike aspect -and orientation are kept in the default family anyway, since a study of compressibility should -not rest on a shift family, but the measurement does not credit them with the growth. - -Two constructions produce that patched input, and `BENCH_PATCH_INPUT` chooses between them. -The default, `norm`, builds one global train per input exactly as case 4 does and hands it to -`add_with_patching`, which truncates each subdomain against its volume share of the global -squared budget and splits whatever still exceeds the cap, choosing the split site by -`BENCH_PATCH_SPLIT`. Every decision it makes comes from Frobenius norms of an already-built -train, and no TCI runs inside the splitting loop. The alternative, `tci`, is -`adaptiveinterpolate`, which never forms a global train at all: it runs a TCI2 per patch on -the function itself and splits a patch whose own TCI does not converge under the cap. That is -the construction this case is eventually written for, since it is the one whose cost never -passes through a global rank. It used to be blocked by an upstream TCI2 defect, -which stopped it from `N` = 32 up on the smooth family's default instance; that is fixed at -the current pin `c9ecb7f` (known issue 11), and the path now completes at smooth `N` = 32 and 64 and at aniso -`N` = 64. `norm` stays the default anyway, and now on the measurement rather than on the -defect: for the same cap the `tci` path splits far harder, 514 and 622 input patches at smooth -`N` = 32 against 6 and 7, so it holds 1.04e6 input parameters against 234952 and returns a -product of 572436 parameters against 129276 at the same accuracy. Making it the default is a -separate decision and is not made here. The price of defaulting to `norm` is exactly the -property `tci` has and it does -not: a global `chi_in` train is built first, so the patched arms of the default sweep pay for -one, and their `input_build_secs` includes it. What the case still measures at equal accuracy -is the size and the cost of the two representations, which is what its conclusion is about. - -The control changes from a budget to an accuracy. A fixed `chi_out` has no meaning for a -patched representation, which has no single rank to cap: its size is a parameter count spread -over patches. So every arm is instead asked for the same global relative tolerance -`BENCH_RTOL`, default `1e-8`, and what the case measures is the size and the wall time each -arm needs to reach it. The error column becomes a check that an arm got there rather than the -discriminator, and `n_params`, the total number of stored core entries, becomes the size -metric, since it is the one number that means the same thing for a single global train and -for a set of patch trains. For a patched arm it counts the free sites of each patch only: the -cores at the projected sites are one-hot copy selectors, structure rather than data, and an -implementation that stored each patch over its free sites would not hold them at all. - -Two details of the tolerance handling are deliberate and are what make the numbers -trustworthy. First, no patch is ever held to a tolerance relative to its own norm, since a -patch sitting in a near-empty corner of the box must be allowed to converge at rank one -instead of being asked for eight relative digits of a quantity that contributes nothing to the -global norm. The `norm` path gets that for free: `add_with_patching` spends `rtol^2 ||F||^2` -over the patches by volume, so the budget of a patch is set by the norm of the whole function. -The `tci` path has to arrange it explicitly, and its per-patch TCI tolerance is therefore -absolute, `rtol` times the sampled scale of the function. Second, the -product is budgeted exactly once, at the end, by `truncate_adaptive`, which spends -`rtol^2 ||F||^2` over the patches proportionally to patch volume and drops a patch whose norm -is below its share. That is the correct treatment of shrinking patch norms; a plain relative -tolerance applied per patch would be the wrong thing. The tolerance handed to the per-patch -engine is kept two orders of magnitude tighter than `rtol` so that it is the final budgeting, -not the engine, that decides where the output is truncated. - -The same rule is why both `aci` paths of this case, the global baseline and the per-patch -engine, run on an ABSOLUTE pivot budget rather than on the upstream default, which since -[tensor4all-rs#619](https://github.com/tensor4all/tensor4all-rs/pull/619) is scale-relative: -the pivot error of a bond divided by the largest output magnitude sampled at that bond. That -default is the right contract for a case whose accuracy target is local, and it is the one -cases 3 and 4 use, but this case measures one global relative error, normalized by the largest -sampled `|f g|` of the whole box, and a per-bond or per-patch normalization is exactly the -per-region relative tolerance the paragraph above refuses. Measured, the difference is not -cosmetic. On the smooth family at `N` = 32, the global `aci` baseline at the same pin and the -same `rtol` returns `chi_out` = 138, 147972 parameters and `8.4e-9` on an absolute budget, -against `chi_out` = 473 pinned at `BENCH_MAX_BOND`, 1.7e6 parameters and `2.7e-1` on the -scale-relative one, which fails the sanity gate; the per-patch engine shows the same thing -one level down, `5.3e-4` for `patched_aci` against `3.5e-8` for the three other engines, and -absolute restores the agreement. Both are recorded as `aci_tolerance` in the params of every -case-5 record. Known issue 13 says what that choice costs the verdict, since a scale-relative -baseline is the smaller object on the aniso family. - -The product itself is formed patch pair by patch pair. Two patches contribute only when their -projectors are compatible, and then the product lives on the intersection of the two -subdomains. Since both inputs cover the domain disjointly, those intersections are disjoint -too and each one is produced exactly once, so no tensor train addition is ever needed. Inside -a pair the product runs on the free sites only, the fixed sites being sliced out of both -inputs first and put back afterwards as one-hot cores. That keeps the work proportional to -the patch volume, and it is what makes the `aci` engine usable at all: on the embedded train -the product vanishes outside a `4^-k` fraction of the index space, so a pivot search seeded -at random points would find nothing but zeros. - -The three default arms `patched_fit_treetn`, `patched_naive` and `patched_aci` are three of the -four engines of case 3 run on the projected patch trains, so a difference between a patched arm -and its global namesake is the patching and not the engine. The fourth, `patched_zipup_treetn`, -is excluded from the defaults on cost alone, the way case 4 excludes `naive`: on the `norm` -path a patch carries a rank near the global one, and a single-pass zip-up of two such patches -with no binding output cap has to form the full product bond before it truncates, which at -`N` = 8 of the smooth family costs 98 s per pass against 3.5 s for each of the other three and -returns the same -product to every reported digit. It is one `BENCH_ALGOS` away. The runner also -measures the two global arms `fit_treetn` and `aci` at the same `rtol` with no binding rank -cap, which is what lets the report put the two representations side by side at equal accuracy. -Each of them has its own `N` ceiling, since the uncapped variational fit and the interpolating -arm are two cost classes: on the smooth family both stop at `N` = 64, and on the aniso family -`aci` runs everywhere while the fit stops at `N` = 1024, the last point measured to keep it -under two minutes (25.1 s there when probed at the pin `1b9a517`, where `aci` cost 0.18 s); -on the `norm` path those two arms run on the very trains the patched inputs were split out of, -so the global construction is counted once and shared. Input construction is timed separately -and recorded as `input_build_secs`, never folded into the product time, since one build is -shared by every arm of an instance. A patched arm on the `norm` path therefore reports the -global build plus the splitting, and a global arm on the same instance reports the global build -alone. - -Measured on the aniso family with the pinned revision on the maintainer's Mac, single-threaded, -at the defaults (`norm` path, cap 64, `rtol` = 1e-8) over the whole default sweep `N` = 8 to -512, which takes 178 s in total, the picture is about the two global arms separately and only -one half of it is a win. Against global `aci`, the interpolating arm, the patched product is -smaller at every point, but only just: 5536, 6560, 17848, 20960, 70128, 82560 and 294680 -parameters against 7456, 8224, 22880, 24480, 92776, 113944 and 312528, all at a relative error -between `2.9e-9` and `4.7e-8`. That margin is 26 percent at `N` = 8 and 6 percent at 512, and -what is behind it is visible in the bond columns: global `aci` reaches `chi_out` = 173, 209 and -256 at `N` = 128, 256 and 512, and 256 is exactly the geometric bound of `R` = 9, while the -patched arms sit at 64 by construction. Read that six percent as a tie rather than as a result, -for two reasons. It is of the order of the run to run spread of the instance itself, whose input -TCI is not bit-reproducible, and it does not survive a different reading of the `aci` baseline's -tolerance: asked for the same `rtol` scale-relative rather than absolute, the same baseline -returns 205008 parameters at `N` = 512 at `5.4e-9`, a third below the patched count, and stops -at `chi_out` = 233 instead of at the geometric bound. That variant is not the default because it -breaks the smooth family (see the tolerance discussion above and known issue 13), but it is -enough to retire the claim that patching beats interpolation on size. Against global -`fit_treetn`, the variational arm, the patched product was never smaller and still is not: -40864 at `N` = 128, 57584 at 256 and 118568 at 512, a factor of 2.5 below the patched count at -the top of the sweep. So an uncapped variational fit remains the smallest representation of this -product, exactly as on the smooth family, and what patching has on size is at best a tie with -interpolation. - -Wall time is the other half, and there the patched arms do win something. `patched_fit_treetn` -costs 0.039, 0.043, -0.218, 0.272, 0.820, 1.03 and 4.27 s, against 0.031, 0.036, 0.179, 0.191, 1.49, 1.85 and -12.48 s for global `fit_treetn`: so from `N` = 128 up the patched fit is cheaper than the -global fit that returns the smaller object, by a factor of 2.9 at `N` = 512, and `patched_aci` -was cheaper there too, by a factor of 2.5 (0.132, 0.102, 0.189, 0.216, 0.849, 0.865 and -4.91 s). Both `aci` arms of this sweep were measured at the pin `b160bb7`, where the ACI global -pivot guard still cost a few tenths of a second per pass, so their wall times are stale at the -current pin and can only have come down (known issue 12): the ordering above therefore stands -and its ratios understate it. Global `aci` cost 0.082 to 0.84 s and stayed roughly an order of -magnitude below everything from `N` = 128 up, as on the smooth family. The -third arm, `patched_naive`, is not competitive at these ranks: 2.17 s at `N` = 64 and 8.46 s at -256 with the same output to every reported digit, since a local bond-Kronecker product forms the -full product bond before it truncates. The three patched arms return identical sizes and errors -at every point, which is expected when nothing binds, and they differ only in wall time. - -The recorded cost breakdown says where that time goes, and it moves with the family. On the -aniso family the per-patch products dominate every arm, 3.39 s of the 4.27 s of -`patched_fit_treetn` at `N` = 512 and 3.83 s of the 4.91 s of `patched_aci`, while the final -`truncate_adaptive` is 0.89 s and 1.08 s. On the smooth family the balance is the other way for -the interpolating arm: at `N` = 64 `truncate_adaptive` is 23.1 s of the 40.1 s of `patched_aci`, -against 4.7 s of the 36.0 s of `patched_fit_treetn`, since the `aci` patches carry larger ranks -into the budgeting than a variational fit leaves behind. The two `patched_aci` splits are the -`b160bb7` ones and share the staleness of that arm's totals; the shape of the split, products -against final budgeting, is what the paragraph is about and the guard does not move it. -Reading a case-5 total without that -split is therefore misleading, which is -why `n_pairs`, `pairs_secs` and `truncate_secs` sit in the params of every patched record. - -What is expensive on the aniso family is neither arm: it is the input construction, and -specifically `add_with_patching`. The patched build costs 0.06, 0.06, 0.23, 0.30, 8.7, 20.5 and -95.0 s over the sweep against 0.02 to 2.31 s for the two global trains it starts from, so from -`N` = 128 up, once the cap really binds and the splitting runs, the splitting is between 95 and -98 percent of it. That is the wall of this case, and it is the reason `N` = 1024 is not in the -default sweep: probed at the defaults at the pin `1b9a517` that point cost 302 s, of which 242 s -is the patched build, against 3.94 s for `patched_fit_treetn`, 1.22 s for `patched_aci` and -25.1 s for the -global fit. Only the `aci` timings of that probe are pin-sensitive, since the -construction and the fit reproduce it to a few percent across the sweep. It is also where the -case gets interesting, since `chi_in` = 256 there is the -geometric bound, so it is one `BENCH_NS` away rather than out of reach. The patched inputs are -also larger than the global ones they were split out of, 116284 against 93856 parameters at -`N` = 128 and 455756 against 267984 at 512, which is the same per-patch overhead the smooth -family shows. - -Measured on the smooth family with the pinned revision on the maintainer's Mac, -single-threaded, at the defaults -(`norm` path, cap 64, `rtol` = 1e-8), the verdict over `N` = 8 to 64 is that patching costs -rather than saves on this instance family. The patched product holds 35952 parameters at -`N` = 8, 107600 at 16, 129276 at 32 and 381332 at 64, against 34752, 50612, 74800 and 114024 -for global `fit_treetn`, which is the smallest representation at every point. So the patched -size is level with the global one at `N` = 8, where the cap does not bind and the construction -returns a single patch, and grows to about three times it at `N` = 64. Against global `aci`, -which is interpolation-based and keeps more, the patched product is the smaller of the two at -`N` = 8 (35952 against 52832) and the larger at 64 (381332 against 292304). All of them sit at -a relative error between `3.8e-9` and `3.8e-8`, so the sizes are comparable at equal accuracy. -The patched inputs cost more still: 67368, 163644, 234952 and 432428 parameters against 103236, -162444, 223324 and 324856 for the two global trains they were split out of. That is a result -about the instance rather than about the implementation: a 2D Gaussian mixture at constant -density is smooth everywhere, so it has no hard region for the patching to isolate, and -subdividing a function that a single train already represents well only pays the per-patch -overhead. What patching buys is bounded rank, 64 here against a global `chi_in` that reaches -142, and the case shows the price of that bound. Wall times are the other half of the picture: -the patched arms cost 2.5, 12.8, 6.5 and 36.0 s for `patched_fit_treetn`, 2.9, 7.9, 8.9 and -22.2 s for `patched_naive` and 3.8, 9.7, 17.2 and 40.1 s for `patched_aci`, against 9.2, 16.4, -20.5 and 31.9 s for global `fit_treetn` and 0.47, 1.44, 1.50 and 2.00 s for global `aci`. So -two of the three patched arms are cheaper than an uncapped global fit at the top of the sweep -and all three lose to global `aci` by one to two orders of magnitude everywhere, and no engine -ordering among them is stable: which of the three is cheapest changes with `N`, since it -depends on how the splitting happened to size the patches. The three arms land on the same -error and the same parameter count to every -reported digit, which is expected here: nothing binds, so each engine computes the same product -to the same tolerance and the final budgeting truncates all of them identically. At equal -accuracy the arms differ in wall time, not in what they return. - -Per-patch rank cap. On the `norm` path the cap decides the entire patch structure, and it -binds hard everywhere the splitting runs at all. Measured in one paired run at `N` = 32 with -the `patched_aci` arm, so that the two halves are comparable with each other rather than with -the sweep's own row, the default cap of 64 leaves 6 and 7 input patches whose largest bond is -62, holding 234952 parameters and built in 41 s, and gives a product of 6 patches and 129276 -parameters -formed in 15.1 s, all of which the later `b160bb7` sweep reproduces (234952 parameters, 39.4 s, -6 patches, 129276 parameters, 17.2 s). Halving the cap to 32 leaves 59 and 67 input patches whose largest bond is -31, holding 540984 parameters and built in 68 s, and gives a product of 72 patches and 312840 -parameters formed in 2.2 s, at the same accuracy, `4.1e-8` against `4.3e-8`. So the cap trades -representation size and construction time against the cost of the per-patch products: more and -smaller patches cost more parameters and a longer build, and make each product much cheaper, -since the work in a patch pair grows like its rank cubed. The default is 64 because this case -is written for large `N`, where a cap of 32 would multiply the patch count by ten at every -point. Where the cap does not bind at all the construction returns a single patch: at `N` = 8 -the volume-budget truncation already brings the global train to bond 63, under the cap, so the -`norm` path splits nothing and the patched arms are the global product with the patch -bookkeeping around it, which is the honest lower end of the sweep rather than a failure. -`BENCH_PATCH_MAX_ITER` applies only to the `tci` path; raising it from the upstream 20 to 200 -changed neither its patch counts nor its patch ranks, at six times the build cost, so the -iteration limit does not drive that splitting either. +| Case | Input and operation | Arms | Scaling axis | +| --- | --- | --- | --- | +| `elementwise_fourier` | Elementwise product of two random one-dimensional Fourier QTTs | naive, zip-up, fit, ACI | measured input χ | +| `gaussian_elementwise` | Elementwise product of randomly rotated anisotropic Gaussian QTTs | global fit, patched fit, global ACI, patched ACI | compressed input χ | +| `gaussian_mpo_contraction` | MPO-MPO contraction of the same Gaussian input family | global fit, patched fit | compressed input χ | -The default sweep depends on the family. On `aniso` it is `N` = 8, 16, 32, 64, 128, 256 and 512, -which runs in 178 s: that family is far cheaper to build per point, since its grid is coarser at -equal `N`, `R` = 9 at `N` = 512 against `R` = 15 for the smooth family at the same count. On -`smooth` it is `N` = 8, 16, 32 and 64, the four points of case 4, so the two cases can be -read against each other over the same factor of eight in `N`. Either way the runner does one -timed pass per arm -rather than the median of three the other cases take: `BENCH_RUNS` defaults to 1 here because -the arms cost tens of seconds each at the top of the smooth sweep while their run to run spread -is -about three percent (2.67, 2.72 and 2.77 s for three passes of `patched_fit_treetn` at -`N` = 8), which is smaller than the spread between two constructions of the same instance, -whose input TCI is not bit-reproducible. On the smooth family `N` = 128 is left out on cost -alone and not because -anything blocks it: probed at the defaults at the pin `1b9a517` it completed in 379 s, of which -297 s is the input -construction, with 28 and 28 input patches, 40 output patches of 520588 parameters, arm times -of 22.4 s for `patched_fit_treetn`, 23.3 s for `patched_naive` and 36.1 s for `patched_aci`, -and a relative error of `1.1e-8`. Only the `patched_aci` time of that probe is pin-sensitive. -That one point costs as much as the whole default sweep, so -it stays one `BENCH_NS` away. -Runner: [`src/bin/elementwise_gauss2d_patched.rs`](src/bin/elementwise_gauss2d_patched.rs), -sweep over `N`. +There is no independent `R` sweep. `R` is the smallest value that gives at least eight grid cells across the fixed minor-axis standard deviation. Gaussian count `N` and `R` are construction metadata, not analysis axes. -### Case 6: patched MPO-MPO fit contraction +## Gaussian input -This case reuses case 5's constant-density anisotropic Gaussian family for -`F(x,y)` and `G(y,z)`. Each function is built once as a quantics MPO. The same -cores and the same shared `y` index objects are copied into -`tensor4all-partitionedtreetn`, using a linear chain and its last site as the -explicit center. Both inputs are split with `add_with_patching`, sequentially -over the shared `y` bits first, and the patched output is computed with -`contract_adaptive` using one full fit sweep. A global `fit_treetn` arm -contracts the same unpatched MPOs with the same output cap and sweep count. -Only the two contraction calls are timed. Input interpolation, HDF5 cache -loading, bridging, patching and output format conversion are outside the timed -region. Deterministic global input trains are cached under `.cache/inputs/` and -reused across reruns; patched inputs are always rebuilt from the cached global -trains. Set `BENCH_INPUT_CACHE_REFRESH=1` to rebuild an entry or -`BENCH_INPUT_CACHE_DIR` to move the cache. A focused test retains the legacy TT -comparison that established numerical equivalence. +Every Gaussian has an independent positive weight, center, log-uniform aspect ratio, and orientation uniform in `[0, pi)`. Each term is independently constructed by two-dimensional `interpolate_multi_scale_nd`. Principal-axis unsafe points spaced by half the minor-axis standard deviation keep the narrow ridge refined. -The default `N = 512` instance targets the practical global-rank range discussed -for case 5. The default per-patch cap is 128; cap 64 is intentionally excluded -from future case-6 measurements. The separate [input-scaling report](result/linux-epyc-7713p/mpo_mpo_aniso_input_scaling.md) -records the established TCI `1e-8` → global relative-L2/SVD `1e-6` → adaptive -cap-128 pipeline through compressed input χ 900, where each input has 120 -patches. For large TCI inputs the runner uses a spatially indexed evaluator with -a recorded rigorous absolute tail bound; sampled errors are checked against the -unmodified full mixture. Regenerate that report from its committed raw records -with `python3 scripts/report_mpo_input_scaling.py result/linux-epyc-7713p`. The committed `N = 2048` crossover sweep is -linked in the [top-level case table](#cases-at-a-glance): patched fit is slower -at input χ 192, faster at χ 224, and 1.60× faster at χ 256 on the recorded -single-core profile. The global output cap is the measured pre-patching -`chi_in`; every local and merged patched contraction is capped at -`BENCH_PATCH_MAX_BOND`. The global arm shows the effect of patching. Naive and -zip-up arms are excluded: -naive scales too steeply at this rank, while the purpose here is the patched fit -path. +The terms are combined by deterministic balanced pairwise reduction. Every pair is added and immediately compressed with the recorded intermediate relative-L2/SVD tolerance. This gives logarithmic reduction depth and avoids an exact intermediate sum whose bond dimension grows with the number of terms. A final global relative-L2/SVD truncation uses `1e-6`. -Accuracy is checked against the finite quantics `y` grid, not against an -unbounded integral. Each anisotropic Gaussian pair is integrated in closed form -on the box and corrected to the left-endpoint grid sum with the first two -Euler-Maclaurin endpoint terms. A unit test compares this reference with the -explicit grid sum. +The expensive raw input pair is cached atomically in `.cache/inputs/`. The cache key includes the schema version, pinned tensor4all-rs revision, `N`, `R`, width, aspect range, spacing, polynomial degree, interpolation tolerance, addition tolerance, and seed. Cases 2 and 3 share the same cache entry. Set `BENCH_INPUT_CACHE_REFRESH=1` to rebuild it or `BENCH_INPUT_CACHE_DIR` to move the cache. -Run single-threaded on one chosen CPU core, for example core 7: +## Patching and accuracy -```bash -RAYON_NUM_THREADS=1 OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 \ -MKL_NUM_THREADS=1 VECLIB_MAXIMUM_THREADS=1 \ -OUT_DIR=/tmp/mpo-mpo-aniso-patched \ -taskset -c 7 cargo run --release --bin mpo_mpo_aniso_patched -``` +The patch cap is fixed at 128 and has no runtime setting. Gaussian fit arms use relative-L2/SVD truncation. ACI uses its own interpolation residual, which is not identified with an L2 tolerance. Records therefore carry both the internal tolerance metric and a common deterministic holdout sampled relative-L2 error. -Runner: [`src/bin/mpo_mpo_aniso_patched.rs`](src/bin/mpo_mpo_aniso_patched.rs), -one default point at `N = 512`. This exploratory case is standalone and is not -included in `scripts/run_all.sh`. +Case 2 compares: -## Latest results +- global fit +- patched fit +- global ACI with scale-relative residual +- patched ACI with patch-local absolute residual followed by global L2 budgeting -One profile per physical machine, so numbers from different hardware never overwrite -each other. Each profile was produced on its own machine, at the revision its own -`run.yaml` records, together with the machine label, the chip, the memory and the pinned -tensor4all-rs revision. A profile is therefore self-describing and is never regenerated on -somebody else's hardware: the report rendering of each profile follows the files committed -with it, so a profile taken before a change to `scripts/report.py` keeps the rendering it -was published with until its own machine runs the sweep again. Compare wall times only -within a profile, and read cross-profile time ratios as statements about hardware -(known issue 10). `run.yaml` also records the thread count the sweep ran with, and profiles -taken before the runner pinned `RAYON_NUM_THREADS=1` were recorded multi-threaded, which is -one more reason not to compare timings across profiles. +Case 3 compares global TreeTN fit with patched chain-TreeTN fit. Its reference is the finite left-endpoint quantics grid contraction, evaluated analytically with endpoint corrections. -`mac-cpu`, the maintainer's Mac, at the full default sweeps, run -single-threaded (`threads: 1`), and the -only profile that carries case 4. It was taken at the pin `1b9a517`, two bumps back, and so -predates the current one: it is kept as that machine's record of the sweep at that revision, -and it is -due a rerun. Spot-checked at the current pin, everything the two bumps changed for cases 1 to 4 -is -in the `aci` wall time column and nothing else: the case-3 default sweep reproduces the -committed `chi_out` = `chi_in` at every `R` and the committed errors to a digit or two, the -case-1 arms reproduce their errors and `chi_out` including the `zipup` arm's `3.9e-6` at -`K` = 128 against its `1e-5` gate, and the case-1 `aci` arm is more than an order of magnitude -slower for the same answer, the global pivot guard's floor of known issue 12. It also predates case 5, -so no profile carries case-5 -records -yet and the case-5 numbers quoted above come from runs on that same machine rather than from a -committed sweep: both families from one full default sweep each at `b160bb7`, whose `aci` arm -times are stale at the current pin (known issue 12), and the two -`N` beyond the defaults from probes at `1b9a517`. The quoted numbers in the case -descriptions above come -from this profile: - -- [`result/mac-cpu/elementwise_fourier.md`](result/mac-cpu/elementwise_fourier.md) -- [`result/mac-cpu/mpo_mpo_quantics.md`](result/mac-cpu/mpo_mpo_quantics.md) -- [`result/mac-cpu/elementwise_gauss2d.md`](result/mac-cpu/elementwise_gauss2d.md) -- [`result/mac-cpu/elementwise_gauss2d_scaling.md`](result/mac-cpu/elementwise_gauss2d_scaling.md) - -The scaling plots sit next to these files. This sweep is current with the `chi_out`-driven -truncation semantics of the fixed-budget cases, so every `chi_out` column sits at the budget -and every arm column is directly comparable at one revision, `1b9a517`. - -`mac-m1-8gb`, an 8 GB Apple M1 MacBook Pro, contributed by a collaborator and kept exactly -as it was committed, at the revision recorded in its own `run.yaml`. It predates the -`chi_out`-driven truncation semantics and case 4, so its fixed-budget arms were still -tolerance-driven and some report a `chi_out` below the budget. It also predates the -single-threaded default and was recorded multi-threaded (`threads: default` in its -`run.yaml`), so none of its wall times are comparable with the single-threaded `mac-cpu` -ones. Read it as that machine's -record of the sweep at that revision, and as the reference point for the memory-bound -naive timings of known issue 10: - -- [`result/mac-m1-8gb/elementwise_fourier.md`](result/mac-m1-8gb/elementwise_fourier.md) -- [`result/mac-m1-8gb/mpo_mpo_quantics.md`](result/mac-m1-8gb/mpo_mpo_quantics.md) -- [`result/mac-m1-8gb/elementwise_gauss2d.md`](result/mac-m1-8gb/elementwise_gauss2d.md) +Input construction, cache I/O, global input compression, format conversion, patch preparation, output conversion, and accuracy evaluation are outside timed regions. ## Running -Prerequisites: - -- Rust (stable toolchain). -- HDF5: `brew install hdf5` on macOS, `sudo apt-get install -y libhdf5-dev` on Debian or - Ubuntu. LAPACK is also linked through `tenferro-linalg`: on macOS the system Accelerate - framework covers it, on Linux install `liblapack-dev` if the build cannot find it. -- [uv](https://docs.astral.sh/uv/) for the report generator (matplotlib, numpy). -- Julia (optional), only for the independent ITensors.jl correctness checks below. - -Full run and report for a machine profile. Name the profile after the machine, one -profile per physical machine, for example: +Requirements are Rust, HDF5, and a BLAS/LAPACK implementation. A complete single-core run is: ```bash -scripts/run_all.sh mac-m1-8gb +BENCH_CPU_CORE=0 scripts/run_all.sh linux-epyc-7713p ``` -This builds in release mode, runs all five cases with their default sweeps into -`result//raw/`, writes `result//run.yaml`, and renders the Markdown -reports and SVG plots. `run.yaml` deliberately records no hostname, only a machine -label (`BENCH_MACHINE`, defaulting to the profile name) plus the chip and memory size, -since a hostname on a public repository can leak the operator's institution and -location. It also stamps `repo_rev` with a `-dirty` suffix when the source tree carries -uncommitted changes, so a sweep can never claim a clean revision it did not come from; -everything under `result/` is excluded from that check, since the script has just -rewritten it. The script pins `RAYON_NUM_THREADS=1` by default so wall times do not -depend on the machine's core count or background load; export `RAYON_NUM_THREADS` -yourself to run multi-threaded, and the value used is recorded in `run.yaml`. On a -machine without `uv`, point `REPORT_PYTHON` at any python that has matplotlib and -numpy. +The script pins Rayon and common BLAS implementations to one thread, runs the three maintained binaries in release mode, writes raw records under `result//raw/`, records machine metadata in `run.yaml`, and generates `report.md`. -Smoke run (small, fast, useful for checking the toolchain). Cases 2 and 3 write the same -`instance-r` file names, so give them different `EXPORT_HDF5` directories when both are -exported; the Julia checks assert the case name and will refuse a mismatched pair: +For a probe run: ```bash -BENCH_KS=4 BENCH_R=10 BENCH_RUNS=1 BENCH_WARMUPS=0 OUT_DIR=/tmp/smoke \ - EXPORT_HDF5=/tmp/smoke cargo run --release --bin elementwise_fourier -BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 \ - OUT_DIR=/tmp/smoke EXPORT_HDF5=/tmp/smoke cargo run --release --bin mpo_mpo_quantics -BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 \ - OUT_DIR=/tmp/smoke EXPORT_HDF5=/tmp/smoke-gauss2d \ - cargo run --release --bin elementwise_gauss2d -BENCH_NS=8 BENCH_R0=8 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 \ - OUT_DIR=/tmp/smoke cargo run --release --bin elementwise_gauss2d_scaling -BENCH_NS=8 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 \ - OUT_DIR=/tmp/smoke cargo run --release --bin elementwise_gauss2d_patched -BENCH_FAMILY=smooth BENCH_NS=8 BENCH_R0=8 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 \ - OUT_DIR=/tmp/smoke cargo run --release --bin elementwise_gauss2d_patched +RAYON_NUM_THREADS=1 OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 \ +MKL_NUM_THREADS=1 VECLIB_MAXIMUM_THREADS=1 \ +BENCH_NS=2 OUT_DIR=/tmp/t4a-probe/raw \ +taskset -c 0 cargo run --release --locked --bin elementwise_gauss2d_patched ``` -Cases 4 and 5 export no HDF5 instances and have no Julia check of their own. Their instances -are the same kind of object as case 3's, a pair of fused site-dimension-4 quantics tensor -trains of Gaussian mixtures, so what an export would verify is already verified by the -case-3 check at `N` = 8, which is the same instance by construction for case 5's `smooth` -family. Case 5 additionally -checks itself against the global representation from inside the crate: a unit test forms the -same product both ways at `R` = 6 and requires the two to agree, which is the statement that -the patching changes the representation and not the function. Its `aniso` family has no case-3 -counterpart and is covered by its own unit tests instead: the drawn quadratic forms against a -hand-computed rotated one, and a four-engine patched product at `R` = 6 against the exact -pointwise product. - -Sanity gates: every runner is self-checking. A runner exits nonzero if any algorithm's -measured error exceeds its gate. Case 1 uses `1e3 * BENCH_TOL` for `naive`, `zipup` and -`aci`, and a looser `1e-2` for `fit` (truncation is norm-relative and the TT norm grows -like `2^(R/2)`, so the pointwise error is not bounded by the tolerance itself). At the top -of the case-1 sweep the `zipup` arm comes within a factor of three of its gate, `3.9e-6` -against `1e-5` at `K` = 128, so extending `BENCH_KS` beyond 128 is likely to trip it; that -would be the gate reporting the growth of single-pass truncation error with the mode count, -not a regression. Case 2 -uses `BENCH_SANITY`, default `1e-2`, for every algorithm: with the output budget fixed at -`chi_in` the truncation error is the quantity the case measures, so the gate only screens -order-unity wrongness. Case 3 uses `BENCH_SANITY` in the same way for `naive`, `fit_treetn` -and `aci`, and a hardcoded `5.0` for `zipup_treetn`, whose fixed-budget error is itself of -order one (known issue 8), so for that arm the gate can only catch a gross scale blow-up or -a non-finite result. Case 4 applies the case-3 rule unchanged, `BENCH_SANITY` for -`fit_treetn` and `aci` and a hardcoded `5.0` for `zipup_treetn`, and additionally fails if -any instance's `chi_in` reaches `BENCH_MAX_BOND`, since a rank pinned at the construction cap -would measure the cap rather than the function. The gates are there to catch wrong results, -not to certify precision. All the gates are absolute and unchanged by the `chi_out`-driven -truncation semantics; only the errors they screen moved. - -Cost note: the quantics rank of the default case-2 mixture saturates around chi = 70 to 80. -`naive` builds the full contracted bond of size chi squared before truncating and is the -only expensive arm: 0.02 s at `R` = 6, 1.1 s at `R` = 8, 32 s at `R` = 10 and 89 to 91 s -at `R` = 12 and 14. Every other arm -stays under a second across that range. At `R` >= 10 the naive intermediates are large -enough that the same points vary with the machine and with ambient memory pressure -(known issue 10). Every algorithm truncates back to -the same -output budget `chi_out <= chi_in`, so the arms differ in accuracy at equal budget rather -than in how far their ranks are allowed to grow. The default sweep (`R` = 6, 8, 10, 12, 14 -with 3 timed runs) is dominated by the naive runs at `R` = 12 and 14 and takes about eleven -minutes single-threaded on the maintainer's Mac, and is by far the most expensive of the -four cases. For the heavy tail, extend explicitly, -for -example `BENCH_RS=6,8,10,12,14,16 BENCH_RUNS=5`. Restrict `BENCH_ALGOS`, dropping `naive`, -when you only want a quick signal. - -Case 3 has the same shape and the same expensive arm, at its own scale: naive costs 0.05 s -at `R` = 6, 3.9 s at `R` = 8 and 6 to 7.6 s at `R` = 10 to 14, and every other arm stays -under one and a half seconds. Its default sweep takes about a minute and a half. Its `aci` -arm is the cheapest of the -four at every `R`, 1 ms at `R` = 6 rising only to 61 ms at `R` = 14, because the pinned -revision includes the ACI rank-saturation early -exit of [tensor4all-rs#591](https://github.com/tensor4all/tensor4all-rs/pull/591), so the -unreachable stopping criterion of the fixed-budget cases no longer makes it run to its -iteration limit. +Gaussian knobs shared by Cases 2 and 3: -Case 5's cost sits in two different places, and on both families the input construction is the -larger one. The default `norm` path builds one global train per input and then splits it, and the -splitting is the expensive half. On the default aniso family the whole construction costs 0.06 s -at `N` = 8, 8.7 s at 128, 20.5 s at 256 and 95.0 s at 512, of which the two global trains are -0.03 s and 2.3 s at the ends, so from `N` = 128 up the splitting is over 95 percent of it. On the -smooth family it is worse per point: at `N` = 64 the two global trains build in 3.5 s and the -whole construction takes 106 s, against 1.3 s at `N` = 8, 17.7 s at 16 and 39.4 s at 32. That -happens once per `N` rather than once per timed run. The patched arms themselves are cheap on the -aniso family, 0.04 to 0.13 s per pass at `N` = 8 and 4.3 to 7.0 s at 512, and expensive on the -smooth one, 2.5 to 3.8 s at `N` = 8 and 22.2 to 40.1 s at 64, so arm cost scales with -`BENCH_RUNS` while the construction does not. The global `fit_treetn` baseline is the most -expensive arm of the smooth sweep, 9.2 s per pass at `N` = 8 rising to 31.9 s at 64, and a -moderate one on the aniso sweep, 0.03 s at `N` = 8 rising to 12.5 s at 512 and 25.1 s at 1024, -since a tolerance-driven fit has no cap to stop it early; both stay under the 120 s per point -that sets the baseline ceilings. The excluded `patched_zipup_treetn` arm is in a class of its own -at 98 s per pass at `N` = 8 of the smooth family. The default aniso sweep takes 178 s with one -timed pass per arm, and the default smooth sweep about seven minutes (measured 418 s). Adding the -next point doubles either: `N` = 1024 of the aniso family costs 302 s, 242 s of it construction, -and `N` = 128 of the smooth family 379 s, 297 s of it construction, so extend explicitly rather -than by default. +| Variable | Default | Meaning | +| --- | ---: | --- | +| `BENCH_NS` | `2,8,32,128` | Gaussian counts used to produce measured χ points | +| `BENCH_SEED` | `0` | deterministic instance seed | +| `BENCH_RUNS` | `1` | timed repetitions | +| `BENCH_WARMUPS` | `0` | untimed repetitions | +| `BENCH_INPUT_CACHE_DIR` | `.cache/inputs` | shared input cache | +| `BENCH_INPUT_CACHE_REFRESH` | `0` | rebuild cache entry when nonzero | +| `OUT_DIR` | `result/dev/raw` | JSON output directory | -Case 4 costs about as much as case 3, but at the pinned revision the quantics TCI -construction of -its inputs is no longer what dominates: at `N` = 64 the two input trains build in a few -seconds, against about 10 s for one timed pass of the three arms (2.5 s for `zipup_treetn`, -7.2 s for `fit_treetn`, 0.2 s for `aci`). Arm cost therefore scales with `BENCH_RUNS` while -the construction runs once per `N`. The default sweep `N` = 8, 16, 32, 64 takes about a minute; -`N` = 128 is left out because the cost roughly doubles again per step and the -fitted exponent is already stable over the factor of 8 in the defaults. All five cases plus -the reports finish in about a quarter of an hour on the maintainer's Mac (measured 823 s for the -first four plus 178 s for case 5 at its default aniso family, or 418 s if case 5 is run on the -smooth family instead), -on top of the -release build, with case 2 accounting for most of it. That figure is for the -single-threaded default, `RAYON_NUM_THREADS=1`, which the runner pins so that wall times do -not depend on the core count or on background load; export `RAYON_NUM_THREADS` yourself to -run multi-threaded and the sweep is correspondingly faster. On a slower or more -memory-constrained machine the same defaults cost -substantially more, most of the difference sitting in the two naive arms at `R` = 10 to 14. +Case 2 additionally accepts `BENCH_ACI_TOL`, default `1e-8`. This is an ACI residual threshold, not an L2 truncation tolerance. -Environment knobs: +Case 1 accepts `BENCH_KS`, `BENCH_R`, `BENCH_TOL`, `BENCH_MAX_BOND`, `BENCH_RUNS`, `BENCH_WARMUPS`, `BENCH_SEED`, and `BENCH_ALGOS`. Its report is sorted by measured input χ even though mode count generates the instances. -| Variable | Applies to | Default | Meaning | -| --- | --- | --- | --- | -| `BENCH_KS` | case 1 | `4,8,16,32,64,128` | comma-separated Fourier mode counts `K` to sweep | -| `BENCH_R` | case 1 | `20` | number of quantics bits | -| `BENCH_RS` | cases 2 and 3 | `6,8,10,12,14` | comma-separated bits per variable `R` to sweep | -| `BENCH_NGAUSS` | cases 2, 3 and 6 | `8` (cases 2 and 3), `512` (case 6) | number of Gaussians or anisotropic spikes per mixture | -| `BENCH_INPUT_CACHE_DIR` | case 6 | `.cache/inputs` | directory for deterministic global input MPS cache entries | -| `BENCH_INPUT_CACHE_REFRESH` | case 6 | unset | when set, rebuild and atomically replace the selected input cache entry | -| `BENCH_INPUT_GENERATOR` | case 6 | `tci` | input constructor: global fused `tci`, or per-Gaussian `multiscale` using principal-axis unsafe points | -| `BENCH_INPUT_TCI_RTOL` | case 6 | `1e-8` | relative TCI tolerance; also the interpolation tolerance supplied to the multiscale constructor | -| `BENCH_TCI_LOCAL_ABS_TOL` | case 6 | `1e-12` | rigorous pointwise absolute bound for tails omitted by the spatially indexed TCI callback | -| `BENCH_TCI_INITIAL_PIVOTS` | case 6 | `8` | deterministic mixture-center grid pivots used by TCI; random initial pivots are disabled | -| `BENCH_INPUT_POLY_DEGREE` | case 6 | `28` | polynomial degree for the multiscale single-Gaussian constructor | -| `BENCH_INPUT_ADD_RTOL` | case 6 | `1e-10` | per-bond SVD tolerance used while adding multiscale single-Gaussian QTTs | -| `BENCH_INPUT_SVD_RTOL` | case 6 | `1e-6` | global relative-L2 SVD tolerance applied before adaptive patching | -| `BENCH_INPUT_ONLY` | case 6 | unset | when set, write the input/patch record and skip contraction | -| `BENCH_INPUT_SANITY` | case 6 | `1e-4` | maximum sampled relative error accepted for each compressed input MPO | -| `BENCH_BOX_L` | cases 2 and 3 | `6.0` | half-width `L` of the box `[-L, L]` | -| `BENCH_NS` | cases 4 and 5 | `8,16,32,64` (case 4, and case 5 on the `smooth` family), `8,16,32,64,128,256,512` (case 5 on the default `aniso` family) | comma-separated Gaussian or spike counts `N` to sweep. Both cases derive `L` and `R` from `N`, so they ignore `BENCH_NGAUSS`, `BENCH_BOX_L` and `BENCH_RS` | -| `BENCH_FAMILY` | case 5 | `aniso` | which instance family to sweep. `aniso` is `N` anisotropic narrow spikes at a fixed spacing-to-width ratio, the family the case is written for; `smooth` is case 4's isotropic Gaussians at constant density, unchanged, and it also switches `BENCH_NS` to case 4's four points. Recorded in the params of every record as `family`, and part of every record's filename, so one profile can hold both | -| `BENCH_ANISO_SIGMA` | case 5 `aniso` family and case 6 | `0.05` | minor width of every spike, in box units. This is the length the grid has to resolve: `R` is chosen so a grid step is at most a quarter of it | -| `BENCH_ANISO_RHO_MAX` | case 5 `aniso` family and case 6 | `8.0` | upper end of the aspect ratio, drawn log-uniform in `[1, BENCH_ANISO_RHO_MAX]` per spike. Setting it to `1` is legal and is the isotropic control: circular spikes of one common shape, everything else unchanged | -| `BENCH_ANISO_SPACING` | case 5 `aniso` family and case 6 | `3.0` | mean spacing between spikes, in minor widths, held fixed as `N` grows. It fixes both the box, `L = BENCH_ANISO_SPACING * sigma * sqrt(N) / 2`, and the overlap of the two mixtures | -| `BENCH_BOX_PADDING` | case 6 | `1.0` | multiplier applied to the case-5 box after drawing the spikes. Keep at 1 for the identical family; larger values add an empty integration margin | -| `BENCH_R_EXTRA` | case 6 | `0` | extra quantics bits beyond case 5's quarter-minor-width resolution | -| `BENCH_MAX_INPUT_CHI` | case 6 | `256` | safety ceiling checked before patch construction or fit; the runner stops instead of starting a contraction above this rank | -| `BENCH_ERROR_SAMPLES` | case 6 | `128` | sampled `(x,z)` points used for the grid-reference error | -| `BENCH_L0` | cases 4 and 5 (`smooth` family) | `6.0` | reference box half-width, the `L` at `N` = `BENCH_N0` | -| `BENCH_N0` | cases 4 and 5 (`smooth` family) | `8` | reference Gaussian count, the `N` at which `L` = `BENCH_L0` and `R` = `BENCH_R0` | -| `BENCH_R0` | cases 4 and 5 (`smooth` family) | `10` | reference bits per variable, the `R` at `N` = `BENCH_N0`. Lower it for a cheap probe of the whole sweep | -| `BENCH_RTOL` | cases 5 and 6 | `1e-8` | case 5's one accuracy knob: the absolute-per-patch input TCI tolerance, global baseline input tolerance, absolute pivot budget of both `aci` arms, and global output budget of both products. Case 6 uses it for global patching, output truncation, and the fit SVD policy | -| `BENCH_PATCH_MAX_BOND` | cases 5 and 6 | `64` (case 5), `128` (case 6) | per-patch rank cap of the patched input construction. A subdomain that does not fit under it is split again; case 6 no longer measures cap 64 | -| `BENCH_PATCH_INPUT` | case 5 | `norm` | which construction produces the patched inputs. `norm` builds one global train per input, exactly as case 4 does, and splits it with `partitionedtt::add_with_patching`, whose decisions come from Frobenius norms alone. `tci` runs `partitionedtt::adaptiveinterpolate` instead, which never forms a global train and splits a patch whose own TCI does not converge under the cap; it is the construction the case is eventually written for, it works at the current pin (known issue 11 records the upstream fix), and it is not the default because for the same cap it splits far harder and returns a much larger representation. Recorded as `input_path` | -| `BENCH_PATCH_SPLIT` | case 5 | `gain` | how the `norm` path picks the site to split. `gain` is the upstream `ExactParameterGain`: it forms and budget-truncates the children of every candidate site and keeps the cheapest. `sequential` takes the first unprojected site of the patch order instead, so the splitting runs strictly coarse to fine and a patch is a single quadrant. Ignored by the `tci` path, whose splitting is sequential by construction. Recorded as `split_strategy` | -| `BENCH_PATCH_MAX_ITER` | case 5, `tci` path | `20` | half-sweep limit of each patch's own TCI run on the `tci` path, the upstream default. It exists as a knob because a run that stops at its limit is not converged and its patch is split whatever its rank was, which would make the patch tree a measurement of the limit; measured, it does not bind, and raising it to 200 changed neither the patch counts nor the patch ranks at six times the build cost. Ignored by the default `norm` path, which runs no TCI, and recorded as `patch_max_iter` either way | -| `BENCH_PATCH_TRACE` | case 5 | unset | set it to any value to print one line per contracted patch pair and one for the final budgeting, for cost-breakdown sessions. It changes nothing that is measured and appears in no record; the per-record breakdown is `n_pairs`, `pairs_secs` and `truncate_secs` | -| `BENCH_PATCH_OUT_MAX_BOND` | case 5 | `BENCH_PATCH_MAX_BOND` squared | rank cap of the per-patch product and of the budgeted output. Left non-binding by default, at the exact product rank of two capped patches, so that `BENCH_RTOL` is the only thing that truncates; the runner fails rather than reports if it binds | -| `BENCH_BASELINES` | case 5 | `1` | whether to also measure the two global arms at the same `rtol`. Each has its own `N` ceiling whatever this says, since they are two cost classes: on the `smooth` family both stop at `N` = 64, and on `aniso` the interpolating `aci` arm runs everywhere while the uncapped global fit stops at `N` = 1024, the last point measured to stay under two minutes for it | -| `BENCH_ALPHA_LO` | cases 2, 3, 4 and 5 (`smooth` family) | `0.5` | lower bound of the Gaussian width parameter | -| `BENCH_ALPHA_HI` | cases 2, 3, 4 and 5 (`smooth` family) | `8.0` | upper bound of the Gaussian width parameter | -| `BENCH_SANITY` | cases 2, 3, 4, 5 and 6 | `1e-2` (cases 2 to 5), `1e-4` (case 6) | relative error gate. Cases 2 and 5 apply it to every algorithm; cases 3 and 4 apply it to all but `zipup_treetn`, which is gated at a hardcoded `5.0`; case 6 applies it to both global and patched grid-reference errors | -| `BENCH_TOL` | cases 1, 2, 3 and 4 | `1e-8` | instance tolerance. In case 1 it is the working tolerance of the whole case, both the input compression and the product. In cases 2, 3 and 4 it is scoped to the input TCI construction only, where it fixes `chi_in` and therefore the instance; the arms take `BENCH_CONTRACT_TOL` instead. It is what each record's top-level `tolerance` field and the Julia-check metadata report, since both describe the inputs. Case 5 has no separate instance tolerance: `BENCH_RTOL` is its one knob and is what its records report | -| `BENCH_CONTRACT_TOL` | cases 2, 3 and 4 | `1e-15` | truncation tolerance handed to every contraction or product arm, recorded as `contract_tol` in the params of each record. At the default it never fires, so the rank cap `chi_in` is the only binding truncation control and the fixed-budget cases are `chi_out`-driven by construction. Raise it if you want a tolerance-driven variant of those cases | -| `BENCH_MAX_BOND` | all | `4096` (case 1), `512` (cases 2 to 5), `384` (case 6) | bond cap for input construction. In cases 2 to 4 it caps only input TCI; case 4 fails if it binds. In case 5 it caps both global baseline inputs and the global trains split by the default `norm` path, and binding is likewise a failure because the train is no longer tolerance-driven. Case 6 records cap-limited crossover points explicitly and separately stops when measured rank exceeds `BENCH_MAX_INPUT_CHI` | -| `BENCH_RUNS` | all | `5` (case 1), `3` (cases 2, 3 and 4), `1` (cases 5 and 6) | timed repetitions, the median is reported | -| `BENCH_WARMUPS` | all | `1` (case 1), `0` (cases 2 to 6) | untimed warmup repetitions | -| `BENCH_SEED` | all | `0` | base seed for instance generation | -| `BENCH_ALGOS` | cases 1 to 5 | `naive,zipup,fit,aci` (case 1), `naive,zipup_simplett,zipup_treetn,fit_treetn` (case 2), `naive,zipup_treetn,fit_treetn,aci` (case 3), `zipup_treetn,fit_treetn,aci` (case 4), `patched_fit_treetn,patched_naive,patched_aci` (case 5) | comma-separated algorithms to run. Case 6 always runs one global and one patched fit arm | -| `OUT_DIR` | all | `result/dev/raw` | directory for the `RunRecord` JSON files | -| `EXPORT_HDF5` | cases 1, 2 and 3 | unset | directory for ITensors-compatible HDF5 instance dumps, plus their JSON metadata. Set it to enable the Julia checks. An empty value counts as unset. Cases 2 and 3 use the same file names, so give them separate directories. Cases 4 and 5 export nothing and ignore it | - -## Julia correctness checks - -The exported instances are read back by ITensors.jl and evaluated against the same -analytic formulas the Rust side uses, which is an engine-independent check that the -inputs really represent the intended functions. First instantiate the environment, then -run a check per instance (the trailing number is `K` for case 1 and `R` for cases 2 and 3, and -the instance must have been exported with `EXPORT_HDF5`). Full profile runs through -`scripts/run_all.sh` do not export HDF5, so to produce instances for the checks set -`EXPORT_HDF5` on a runner invocation of your own, for example the case-1 smoke run above -with `EXPORT_HDF5=/tmp/smoke`: +## Validation ```bash -julia --project=julia -e 'using Pkg; Pkg.instantiate()' -julia --project=julia julia/check_elementwise.jl /tmp/smoke 4 -julia --project=julia julia/check_mpo_mpo.jl /tmp/smoke 8 -julia --project=julia julia/check_elementwise_gauss2d.jl /tmp/smoke-gauss2d 8 +cargo fmt --all -- --check +cargo test --release +cargo clippy --locked --all-targets -- -D warnings +cargo check --locked --all-targets +python3 scripts/report.py result/ +git diff --check ``` -Cases 1 and 3 export the exact tensor trains that were benchmarked. Case-2 exported -instances, by contrast, are re-generated by TCI at export time, so they can differ slightly -from the exact tensors used in the timed runs (see known issue 5); the function-level check -remains valid, since both the exported instance and the benchmarked one approximate the same -analytic mixture to the working tolerance. - -`check_mpo_mpo.jl` and `check_elementwise_gauss2d.jl` are near identical, because the two -cases export the same kind of instance, a pair of fused site-dimension-4 quantics tensor -trains of Gaussian mixtures. Each asserts its own case name in the instance JSON, so -pointing one at the other case's export directory fails loudly instead of silently checking -the wrong instance. - -## Known issues - -1. **`tensor4all_simplett::mpo::contract_fit` is a silent placeholder at the pinned - revision.** Its two-site local update leaves the core untouched, so the routine - returns the naive contraction and the sweeps are dead work, with environments built by - impractical scalar loops. It fails no test and prints no warning. Upstream issue: - [tensor4all-rs#571](https://github.com/tensor4all/tensor4all-rs/issues/571). This - benchmark therefore has no simplett fit arm: the case-2 fit is `fit_treetn`, run on the - `tensor4all-treetn` engine bridged via `tensor4all-itensorlike`, which has a complete - fit implementation. -2. **Case 2 mixes engines.** `naive` and `zipup_simplett` run on `simplett`, `zipup_treetn` - and `fit_treetn` on `treetn`. Both engines truncate relative to the largest singular - value at the pinned revision, and the rank cap binds for all of them at - `chi_out <= chi_in`, so the two zipup arms now return the same result and their - remaining difference is wall time. Running zipup on both engines is what makes that - difference measurable instead of confounded with the algorithm. The generated report - repeats this note under its summary table. The `fit_treetn` arm also runs a single full - sweep, pinned as part of the benchmark definition and recorded as `fit_nsweeps` in every - JSON record, so its wall time is only comparable at that stated sweep count. -3. **The case-1 `fit` arm is pinned to two full sweeps.** The sweep count is part of the - benchmark definition, since fit cost is linear in it. The upstream elementwise fit - accuracy problem recorded in `tensor4all-itensorlike/tests/bug_fit_elementwise.rs` did - not reproduce on the instances used here, so the arm is kept in the defaults, with a - loosened sanity gate as a guard. -4. **Case 2 has a reference error floor.** The analytic reference integrates - `y` over the whole real line, while the MPO contraction sums only over the box, so the - two differ by the tail outside the box. Error curves that plateau at a level independent - of the algorithm are hitting the reference, not a tensor network artifact. The level was - quoted here as around `1e-8` from the tolerance-driven results; with the contraction now - `chi_out`-driven, `naive` and `fit_treetn` reach `5.7e-10` at `R` = 6 and `2.3e-9` at - `R` = 8, so at the default box size the floor sits below `1e-8` and the earlier figure was - the truncation error of those arms rather than the reference. -5. **Quantics TCI construction is not bit-reproducible across runs** in cases 2, 3 and 4, - even at a fixed seed: the input bond dimension can vary by one or two between runs of - the same instance. Consecutive case-3 sweeps at identical code and seeds gave `chi_in` - of 53, 75, 77 and then 53, 76, 79. The recorded `input_max_bond_dim` always reflects - the actual run, so the plots stay self-consistent, but two runs of the same - configuration can differ slightly on the x axis. -6. **Resolved upstream, included in the pinned revision.** - [tensor4all-rs#574](https://github.com/tensor4all/tensor4all-rs/pull/574) fixed three - simplett defects that this benchmark had recorded as case-2 anomalies: MPO factorize - truncated against an absolute singular value threshold and now truncates relative to - the largest singular value, matching treetn; `contract_zipup` ran an eight-deep scalar - loop and now uses einsum, about 800 times faster, which removes the two to three orders - of magnitude engine gap the earlier results showed on the zipup arms; and - `contract_naive`'s compression sweep now establishes a right-to-left QR gauge before - truncating, which dropped its error by about three orders of magnitude so that naive - matches the variational fit. All three are contained in the current pin `c9ecb7f`, as they - were in the earlier pins `7cfec22`, where they first landed, `1b9a517`, which added - [tensor4all-rs#575](https://github.com/tensor4all/tensor4all-rs/pull/575), a treetci - convergence fix that stops input TCI construction early once the rank saturates at - `max_bond_dim`, and `b160bb7`. Earlier numbers in this repository's git history predate these fixes and - are not comparable. -7. **simplett has no elementwise product for tensor trains at the pinned revision.** It - offers MPO-MPO contraction (`contract_naive`, `contract_zipup`, the stubbed - `contract_fit`) but nothing that forms a Hadamard product of two tensor trains, so cases - 1 and 3 have no simplett arm and case 3 cannot put two engines on one algorithm the way - case 2 does with its pair of zipup arms. Its `naive` arm is therefore written in this - repository, as a core-wise bond Kronecker product plus an SVD sweep on simplett - primitives, and is recorded with `engine` = `local` to keep that visible. -8. **Case-3 `zipup_treetn` has no correct digits at the fixed output budget.** It returns a - relative error of order one, between `1.3e-1` and `1.1` depending on `R`, on `N` and on the - run, across the default sweeps of cases 3 and 4, having spent the whole - `chi_in` budget. This is a property of the case, not a defect of the arm: the exact - elementwise product has rank up to `chi_in` squared, and given more room the same arm - converges normally, to `1.8e-7` at 8 `chi_in` and `3.9e-8` unconstrained. Because the - error is of order one, the sanity gate cannot screen order-unity wrongness for this arm, - so it is gated at a hardcoded `5.0` that only catches a scale blow-up or a non-finite - result. Read the case-3 zipup error column as a verdict on the budget rather than as a - precision measurement. Case 4 inherits all of this: it runs the same arm at the same fixed - budget on the same kind of instance, at roughly twice the rank, and sees the same - order-unity error. -9. **Resolved upstream: ACI no longer runs to its iteration limit when the cap binds.** The - fixed-budget cases hand every arm an unreachable tolerance so that the rank cap alone - decides the truncation, and for - `aci` that used to mean the stopping criterion never fired and the sweep ran to - `AciOptions::max_iters` even after the pivots had saturated, which made the `aci` arm of - cases 3 and 4 cost far more wall time than the algorithm needed. Its accuracy was never - affected. The early exit on rank saturation landed in - [tensor4all-rs#591](https://github.com/tensor4all/tensor4all-rs/pull/591) and is included - at the current pin `c9ecb7f`, and the fresh sweep confirms the fix: `aci` is now the - cheapest arm at every point of cases 3 and 4, six to fourteen times below `zipup_treetn`, - with the same errors as before. Numbers quoted in this repository's git history from before - the bump are not comparable on the `aci` column. The `mac-m1-8gb` profile predates this - pin, so its `aci` column still shows the pre-fix cost. -10. **`naive` wall times at `R` >= 10 are machine bound.** The naive arms form intermediates - of bond `chi_in` squared, which at chi around 80 press against the free memory of a - smaller machine, so their wall time depends on the hardware and on ambient memory - pressure rather than on the algorithm alone. The clearest evidence is a comparison on one - machine: on the 8 GB M1 of the `mac-m1-8gb` profile, both runs multi-threaded, the case-2 - point at `R` = 10 measured about 28 s per run on a session with swap nearly - full and 16 s on the same machine right after a reboot, same code, same errors, same - `chi_out`; the committed sweep is the post-reboot one, taken on an otherwise idle - machine, where the spread across the three timed runs stays within about 5 percent at - `R` = 12 and 14 (22 percent at `R` = 10, whose first run pays the page-in). The - `mac-cpu` profile measures the same `R` = 10 point at about 32 s, but that number is - single-threaded on different hardware, so it says nothing about the two figures above. - The cheap arms differ far - less. Errors and bond dimensions are unaffected everywhere, since the computation is - the same arithmetic either way. So compare naive timings only within one profile, run - official sweeps on an idle machine, and read cross-profile time ratios as hardware - statements. This is also why profiles are per machine and why `run.yaml` records the - chip and memory. - -11. **Resolved upstream: the TCI-driven input construction of case 5 no longer trips a - bond mismatch.** With `BENCH_PATCH_INPUT=tci` the construction of a patched input used - to fail with `Tensor train error: Dimension mismatch: tensor at site k has incompatible - dimensions`, raised where `adaptiveinterpolate` turns an accepted patch's TCI into a - tensor train, so the TCI2 site tensors of that patch did not agree on their shared bond. - It was deterministic and instance specific, and it stopped the `tci` path from `N` = 32 - up on the default smooth instance, which is why `norm` became the default construction. - [tensor4all-rs#602](https://github.com/tensor4all/tensor4all-rs/pull/602) fixed it - upstream (issue - [#598](https://github.com/tensor4all/tensor4all-rs/issues/598)) and the fix is included - at the current pin `c9ecb7f`. Verified at the previously failing point and beyond: the - `tci` path now completes at `N` = 32 and 64 of the smooth family and at `N` = 64 of the - aniso family. `norm` nonetheless stays the default, on the measurement rather than on the - defect: the `tci` path splits far harder for the same cap, 514 and 622 input patches at - smooth `N` = 32 against 6 and 7 for `norm`, so it holds 1.04e6 input parameters against - 234952 and returns a product of 572436 parameters against 129276 at the same accuracy. - Which of the two constructions should be the default is therefore a separate decision - from this fix, and it is not made here. One caveat if you run it: the per-patch `aci` - engine loses accuracy on the many tiny patches that path produces (`2.9e-5` at smooth - `N` = 32 and `4.3e-4` at 64, against `1.7e-8` and `2.2e-8` for the other three engines), - so read `patched_aci` on the `tci` path with suspicion. - -12. **Resolved upstream: the ACI global pivot guard no longer dominates the wall time of a - many-site instance.** `AciOptions` gained a global pivot guard in - [tensor4all-rs#610](https://github.com/tensor4all/tensor4all-rs/pull/610), on by default, - which runs several floating-zone walks over the index space after every sweep and only - accepts convergence once they find nothing. It buys robustness against a feature that no - bond-local error estimate can see, and its cost grows with the site count rather than with - the rank. As first written the guard rebuilt its evaluation cache and recompiled an einsum - per call, which at the pin `b160bb7` cost the case-1 `aci` arm, on `R` = 20 sites, 0.9 to - 1.3 s per pass against 0.4 to 1.2 ms at the pre-guard pin `1b9a517`, three orders of - magnitude for the same answer. - [tensor4all-rs#621](https://github.com/tensor4all/tensor4all-rs/pull/621) (issue - [#620](https://github.com/tensor4all/tensor4all-rs/issues/620)) fixed that at the current - pin `c9ecb7f`: the guard now reuses one `TTCache` across sweeps, keeps a single solution - cache per invocation, and applies its mat-vec inline instead of recompiling an einsum per - call. Re-measured at `c9ecb7f`, the case-1 `aci` arm costs 14 to 21 ms per pass over the - default `K` sweep, with ranks and errors unchanged and `chi_out` of 9, 15, 16, 22, 29 and - 32. What remains is a floor of roughly 15 ms per pass on a many-site instance, which is - the guard doing the work it exists for and is the safety contract of #610 rather than a - defect: the case-1 arm is still an order of magnitude above its pre-guard cost and will - stay there while the guard is on. Cases 3 and 4, on 6 to 14 fused sites, never moved - measurably. The `aci` columns of the committed `mac-cpu` sweep were taken at the pre-guard - pin `1b9a517`, so case 1's is low by that floor until that machine reruns; anything quoted - in this repository's git history from the `b160bb7` window is stale on the `aci` column in - the other direction. - -13. **The case-5 size verdict against global `aci` depends on how that baseline's tolerance is - read.** Case 5 runs both its `aci` paths on an absolute pivot budget, `BENCH_RTOL` against - an output of order one, because its accuracy target is one global relative error and the - upstream default since - [tensor4all-rs#619](https://github.com/tensor4all/tensor4all-rs/pull/619) normalizes per - bond instead. That choice is forced: measured on the smooth family, the scale-relative - variant of the same baseline runs its rank to `BENCH_MAX_BOND` and returns `2.7e-1` at - `N` = 32 and `2.8e-1` at 64, which fails the sanity gate, and the per-patch `aci` engine - loses four to six orders of magnitude of accuracy against the other three engines on the - same instances. But on the aniso family the scale-relative variant is both accurate and - smaller than the absolute one, 205008 parameters against 312528 at `N` = 512 at `5.4e-9`, - below the patched product's 294680. So the six percent size margin the default sweep - reports for patching over global `aci` at the top of the aniso sweep is not robust to this - knob, and the README verdict says so. What does not depend on it is the comparison against - the global variational fit, which is the smallest representation on both families, and the - wall time ordering, where the patched arms beat that fit from `N` = 128 up. A tolerance - contract that is per-region for the pivot search and global for the reported error is the - real gap, and closing it upstream is what would make this margin a measurement. - -## License - -MIT, see [`LICENSE`](LICENSE). +The focused tests cover difficult rotated interpolation, balanced pairwise sums, cache round trips, index identity, global and patched fit/ACI accuracy, contraction accuracy, patch caps, parameter accounting, and JSON serialization. diff --git a/docs/superpowers/plans/2026-08-04-tensor4all-benchmark.md b/docs/superpowers/plans/2026-08-04-tensor4all-benchmark.md deleted file mode 100644 index e735e84..0000000 --- a/docs/superpowers/plans/2026-08-04-tensor4all-benchmark.md +++ /dev/null @@ -1,1760 +0,0 @@ -# tensor4all-benchmark Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. -> **Per user instruction: implementation subagents must run on the Opus model** (Agent tool `model: "opus"`). - -**Goal:** Public benchmark repo comparing tensor4all-rs algorithms on two cases: (1) elementwise product of random Fourier series QTTs (naive/zipup/fit/ACI), (2) MPO-MPO contraction of 2D quantics Gaussian mixtures (naive/zipup/fit) with an analytic reference. - -**Architecture:** Single Rust package (lib + two runner binaries) with git-pinned tensor4all-rs dependencies. Runners emit versioned JSON to `result//raw/`; a uv Python script renders Markdown reports with SVG scaling plots. Inputs are generated in Rust only and handed to a Julia correctness script via ITensor-compatible HDF5 plus a JSON instance file. - -**Tech Stack:** Rust (tensor4all-simplett, tensor4all-aci, tensor4all-treetn, tensor4all-quanticstci, tensor4all-hdf5, serde, rand_chacha), Python via uv (matplotlib), Julia (ITensors.jl, HDF5.jl, JSON3.jl). - -## Global Constraints - -- Repo root: this repository (git repo already initialized, spec committed at `docs/superpowers/specs/2026-08-04-tensor4all-benchmark-design.md`). -- tensor4all-rs pinned via git: `git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e"`. The API signatures below were read from the local checkout on a slightly newer branch; if a signature does not compile against the pin, first try bumping the rev to the current origin/main head, and record the final rev in this plan file. -- All tensor4all crates must use their default backend feature (`tenferro-cpu-faer`) consistently. Do not mix backends. -- `tensor4all-hdf5` needs a system HDF5 at build time (`brew install hdf5` on macOS, `libhdf5-dev` on Linux CI). -- All randomness through `rand_chacha::ChaCha8Rng` with explicit seeds recorded in JSON output. -- JSON records carry `schema_version: 1`. -- Every runner fails with nonzero exit if any algorithm error exceeds its sanity bound, so wrong timings never reach reports. -- Prose style in README and reports: no em/en dashes anywhere (user rule); use commas, colons, or separate sentences. -- Commit messages end with `Co-Authored-By: Claude Fable 5 `. - -## Key upstream API facts (verified against local tensor4all-rs checkout) - -- `tensor4all_simplett`: `TensorTrain::new(Vec>)`, `tensor3_from_data(data, left, site, right)` (column-major, index `l + left*(s + site*r)`), trait `AbstractTensorTrain` provides `evaluate(&[usize])`, `rank()`, `link_dims()`, `norm()`. `TensorTrain::compress(&CompressionOptions { method: CompressionMethod::SVD, tolerance, max_bond_dim, normalize_error })`. -- `tensor4all_simplett::mpo`: `MPO::new(Vec>)`, `tensor4_from_data(data, l, s1, s2, r)` (column-major), `MPO::evaluate(&[usize])` takes 2L interleaved indices `[i1, j1, i2, j2, ...]`. Contractions: `contract_naive(&a, &b, Option)`, `contract_zipup(&a, &b, &ContractionOptions)`, `contract_fit(&a, &b, &FitOptions, Option>)`. `ContractionOptions { tolerance, max_bond_dim, factorize_method }`, `FitOptions { tolerance, max_bond_dim, max_sweeps, convergence_tol, factorize_method }`. -- `tensor4all_aci`: `elementwise(|xs: &[T]| ..., &[TensorTrain], &AciOptions) -> Result>`, `AciOptions { max_iters, min_iters, max_bond_dim, tolerance, scale_tolerance, initial_guess, rng_seed }`, `AciResult { tensor_train, ranks, errors }`. T is `f64` or `Complex64`. -- `tensor4all_treetn`: `hadamard(&left_treetn, &right_treetn, &[(DynIndex, DynIndex)], ¢er_node, ContractionOptions)`; bridges `tensor_train_to_treetn(&TensorTrain) -> Result<(TreeTN, Vec)>` and `treetn_to_tensor_train::(TreeTN<...>) -> Result>`. `tensor4all_treetn::contraction::ContractionOptions` has public fields `method: ContractionMethod` (Zipup/Fit/Naive), `max_rank`, `svd_policy`, `nfullsweeps`, `convergence_tol` and more; check exact field types at `crates/tensor4all-treetn/src/treetn/contraction.rs` when compiling. -- `tensor4all_quanticstci`: `quanticscrossinterpolate(&DiscretizedGrid, f: Fn(&[f64]) -> V, None, QtciOptions) -> (QuanticsTensorCI2, ranks, errors)`; `DiscretizedGrid::builder(&[R, R]).with_lower_bound(..).with_upper_bound(..).with_unfolding_scheme(UnfoldingScheme::Fused).build()`; `qtci.tensor_train()` returns `tensor4all_simplett::TensorTrain` with site dim 4 per site (fused 2D), fused local index is `x_bit + 2*y_bit` (x least significant; verify by test, transpose helper provided as fallback). `QtciOptions` builders: `with_tolerance`, `with_maxbonddim`, `with_unfoldingscheme`. -- `tensor4all_hdf5`: `save_mps(path, name, &tensor4all_itensorlike::TensorTrain)`, `append_mps`, ITensors.jl-compatible (`@type = "MPS"`). Consumes itensorlike TT only; bridge: simplett TT -> `tensor_train_to_treetn` -> `tensor4all_itensorlike::TensorTrain::from_treetn(treetn)`. -- Quantics bit convention: MSB first, grid index `i = sum_n s_n 2^(R-1-n)`, `x = lower + i*step`, `step = (upper-lower)/2^R`, half-open grid. - -## File structure - -``` -Cargo.toml package t4a-bench (lib + bins) -src/lib.rs module decls -src/harness.rs timing (median of N), sample index helper -src/record.rs RunRecord JSON schema + writer -src/fourier.rs FourierSeries: random gen, eval, convolution, to_qtt -src/elementwise.rs 4 algorithm wrappers + error measurement -src/gaussian.rs GaussianMixture2D, analytic y-integral, to_quantics_mpo -src/mpo_contract.rs 3 MPO contraction wrappers + error measurement -src/hdf5_export.rs simplett TT -> HDF5 (via itensorlike bridge) -src/bin/elementwise_fourier.rs runner (case 1) -src/bin/mpo_mpo_quantics.rs runner (case 2) -julia/Project.toml ITensors, HDF5, JSON3 -julia/check_elementwise.jl case 1 correctness check -julia/check_mpo_mpo.jl case 2 correctness check -scripts/run_all.sh full local run -scripts/report.py JSON -> Markdown + SVG plots -pyproject.toml uv config (matplotlib, numpy) -result// committed reports (created by runs) -.github/workflows/ci.yml build + test + smoke -README.md -``` - ---- - -### Task 1: Package scaffold and shared harness - -**Files:** -- Create: `Cargo.toml`, `.gitignore`, `src/lib.rs`, `src/harness.rs`, `src/record.rs` - -**Interfaces:** -- Produces: `t4a_bench::harness::{time_median, Timing, sample_grid_indices}`, `t4a_bench::record::{RunRecord, write_record}`. Later tasks import these exactly as named. - -- [ ] **Step 1: Write Cargo.toml and .gitignore** - -`Cargo.toml`: - -```toml -[package] -name = "t4a-bench" -version = "0.1.0" -edition = "2021" -license = "MIT" -publish = false - -[dependencies] -tensor4all-simplett = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-simplett" } -tensor4all-aci = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-aci" } -tensor4all-treetn = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-treetn" } -tensor4all-itensorlike = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-itensorlike" } -tensor4all-quanticstci = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-quanticstci" } -tensor4all-hdf5 = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-hdf5" } -tensor4all-core = { git = "https://github.com/tensor4all/tensor4all-rs", rev = "69a24e7e86edc7079b758784864e3976776d208e", package = "tensor4all-core" } -num-complex = "0.4" -rand = "0.8" -rand_chacha = "0.3" -serde = { version = "1", features = ["derive"] } -serde_json = "1" -anyhow = "1" - -[profile.release] -debug = true -``` - -Note: if the pinned rev fails to build or an API below is missing, bump every `rev` to current `origin/main` of tensor4all-rs and record the new rev here. If `rand` 0.8 conflicts with workspace deps, match the version tensor4all-rs uses. - -`.gitignore`: - -``` -/target -Cargo.lock.orig -__pycache__/ -.venv/ -julia/Manifest.toml -result/**/raw/*.h5 -``` - -(Cargo.lock IS committed: this is a binary-style repo.) - -- [ ] **Step 2: Write failing test for harness** - -`src/harness.rs` (test first, at bottom of the new file with stub-free implementation in step 3; create the file with only the test module and `use` lines, expect compile failure): - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn time_median_returns_result_and_positive_times() { - let (val, timing) = time_median(1, 3, || 40 + 2); - assert_eq!(val, 42); - assert_eq!(timing.runs_secs.len(), 3); - assert!(timing.median_secs >= 0.0); - } - - #[test] - fn sample_grid_indices_is_deterministic_and_in_range() { - let a = sample_grid_indices(10, 64, 7); - let b = sample_grid_indices(10, 64, 7); - assert_eq!(a, b); - assert_eq!(a.len(), 64); - assert!(a.iter().all(|&i| i < 1u64 << 10)); - } -} -``` - -- [ ] **Step 3: Run test to verify it fails** - -Run: `cargo test harness -- --nocapture` -Expected: compile error, `time_median` not found. - -- [ ] **Step 4: Implement harness** - -Fill in `src/harness.rs` above the test module: - -```rust -use rand::Rng; -use rand::SeedableRng; -use rand_chacha::ChaCha8Rng; -use std::time::Instant; - -pub struct Timing { - pub median_secs: f64, - pub runs_secs: Vec, -} - -/// Run `f` `warmups` times untimed, then `repeats` times timed. -/// Returns the last result and the timing summary. -pub fn time_median(warmups: usize, repeats: usize, mut f: impl FnMut() -> R) -> (R, Timing) { - assert!(repeats >= 1); - for _ in 0..warmups { - std::hint::black_box(f()); - } - let mut runs_secs = Vec::with_capacity(repeats); - let mut last = None; - for _ in 0..repeats { - let t0 = Instant::now(); - last = Some(std::hint::black_box(f())); - runs_secs.push(t0.elapsed().as_secs_f64()); - } - let mut sorted = runs_secs.clone(); - sorted.sort_by(|a, b| a.partial_cmp(b).unwrap()); - let median_secs = sorted[sorted.len() / 2]; - (last.unwrap(), Timing { median_secs, runs_secs }) -} - -/// `n` random grid indices in [0, 2^r), deterministic in `seed`. -pub fn sample_grid_indices(r: usize, n: usize, seed: u64) -> Vec { - let mut rng = ChaCha8Rng::seed_from_u64(seed); - (0..n).map(|_| rng.gen_range(0..(1u64 << r))).collect() -} - -/// MSB-first bit decomposition of a grid index into R local indices. -pub fn index_to_bits(i: u64, r: usize) -> Vec { - (0..r).map(|n| ((i >> (r - 1 - n)) & 1) as usize).collect() -} -``` - -Add a third test in the test module: - -```rust - #[test] - fn index_to_bits_msb_first() { - assert_eq!(index_to_bits(0b100, 3), vec![1, 0, 0]); - assert_eq!(index_to_bits(0b011, 3), vec![0, 1, 1]); - } -``` - -- [ ] **Step 5: Implement record.rs with test** - -`src/record.rs`: - -```rust -use serde::Serialize; -use std::path::Path; - -pub const SCHEMA_VERSION: u32 = 1; - -#[derive(Serialize)] -pub struct RunRecord { - pub schema_version: u32, - pub case: String, - pub algorithm: String, - pub params: serde_json::Value, - pub seed: u64, - pub tolerance: f64, - pub wall_time_median_secs: f64, - pub wall_times_secs: Vec, - pub max_error: f64, - pub input_max_bond_dim: usize, - pub output_max_bond_dim: usize, - pub output_bond_dims: Vec, -} - -pub fn write_record(dir: &Path, name: &str, record: &RunRecord) -> anyhow::Result<()> { - std::fs::create_dir_all(dir)?; - let path = dir.join(format!("{name}.json")); - std::fs::write(&path, serde_json::to_string_pretty(record)?)?; - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn record_roundtrips_to_json() { - let rec = RunRecord { - schema_version: SCHEMA_VERSION, - case: "elementwise_fourier".into(), - algorithm: "aci".into(), - params: serde_json::json!({"k_max": 8, "r": 12}), - seed: 0, - tolerance: 1e-8, - wall_time_median_secs: 0.1, - wall_times_secs: vec![0.1], - max_error: 1e-9, - input_max_bond_dim: 5, - output_max_bond_dim: 9, - output_bond_dims: vec![2, 9, 2], - }; - let s = serde_json::to_string(&rec).unwrap(); - let v: serde_json::Value = serde_json::from_str(&s).unwrap(); - assert_eq!(v["schema_version"], 1); - assert_eq!(v["params"]["k_max"], 8); - } -} -``` - -`src/lib.rs`: - -```rust -pub mod harness; -pub mod record; -``` - -- [ ] **Step 6: Run tests, verify pass** - -Run: `cargo test` -Expected: all tests pass (first build compiles the pinned tensor4all-rs, takes minutes). - -- [ ] **Step 7: Commit** - -```bash -git add -A && git commit -m "feat: scaffold t4a-bench package with timing harness and JSON record schema" -``` - ---- - -### Task 2: Random Fourier series and exact QTT construction - -**Files:** -- Create: `src/fourier.rs` -- Modify: `src/lib.rs` (add `pub mod fourier;`) - -**Interfaces:** -- Consumes: `harness::index_to_bits`. -- Produces: `t4a_bench::fourier::FourierSeries` with `pub coeffs: Vec`, `fn random(k_max: usize, seed: u64) -> Self`, `fn eval(&self, x: f64) -> Complex64`, `fn product(&self, other: &Self) -> Self`, `fn to_qtt(&self, r: usize) -> anyhow::Result>`, and free fn `compress_svd(tt: &mut TensorTrain, tol: f64, max_bond: usize) -> anyhow::Result<()>`. - -Math: series `f(x) = sum_{k=0}^{K} c_k exp(2 pi i k x)` on `x in [0,1)`. Each mode is exactly rank 1 in quantics because `x = sum_n s_n 2^{-(n+1)}` (MSB first), so `exp(2 pi i k x) = prod_n exp(2 pi i k s_n / 2^{n+1})`. The sum of K+1 modes is an exact QTT of bond dimension K+1 with mode-diagonal cores. Coefficients: re and im each U[0,1], then normalized so `sum |c_k|^2 = 1` (Ritter, arXiv:2604.00037). The product of two series is the coefficient convolution, band limit 2K. - -- [ ] **Step 1: Write failing tests** - -```rust -#[cfg(test)] -mod tests { - use super::*; - use crate::harness::{index_to_bits, sample_grid_indices}; - use tensor4all_simplett::AbstractTensorTrain; - - #[test] - fn random_series_is_normalized_and_deterministic() { - let f = FourierSeries::random(8, 42); - let g = FourierSeries::random(8, 42); - assert_eq!(f.coeffs, g.coeffs); - let n2: f64 = f.coeffs.iter().map(|c| c.norm_sqr()).sum(); - assert!((n2 - 1.0).abs() < 1e-12); - assert_eq!(f.coeffs.len(), 9); - } - - #[test] - fn qtt_matches_direct_evaluation() { - let r = 10; - let f = FourierSeries::random(6, 1); - let tt = f.to_qtt(r).unwrap(); - for &i in &sample_grid_indices(r, 50, 2) { - let x = i as f64 / (1u64 << r) as f64; - let bits = index_to_bits(i, r); - let v = tt.evaluate(&bits).unwrap(); - assert!((v - f.eval(x)).norm() < 1e-11, "mismatch at x={x}"); - } - } - - #[test] - fn product_is_coefficient_convolution() { - let f = FourierSeries::random(3, 1); - let g = FourierSeries::random(4, 2); - let p = f.product(&g); - assert_eq!(p.coeffs.len(), 3 + 4 + 1); - let x = 0.371; - assert!((p.eval(x) - f.eval(x) * g.eval(x)).norm() < 1e-12); - } - - #[test] - fn compression_reduces_rank_below_k_plus_one() { - let r = 14; - let k = 32; - let f = FourierSeries::random(k, 7); - let mut tt = f.to_qtt(r).unwrap(); - assert_eq!(tt.rank(), k + 1); - compress_svd(&mut tt, 1e-10, usize::MAX).unwrap(); - assert!(tt.rank() < k + 1, "rank {} not reduced", tt.rank()); - for &i in &sample_grid_indices(r, 20, 3) { - let x = i as f64 / (1u64 << r) as f64; - let v = tt.evaluate(&index_to_bits(i, r)).unwrap(); - assert!((v - f.eval(x)).norm() < 1e-8); - } - } -} -``` - -- [ ] **Step 2: Run tests, verify compile failure** - -Run: `cargo test fourier` -Expected: FAIL, module missing. - -- [ ] **Step 3: Implement** - -```rust -use num_complex::Complex64; -use rand::Rng; -use rand::SeedableRng; -use rand_chacha::ChaCha8Rng; -use tensor4all_simplett::{tensor3_from_data, CompressionMethod, CompressionOptions, TensorTrain}; - -#[derive(Clone, Debug)] -pub struct FourierSeries { - /// c_k for k = 0..=K - pub coeffs: Vec, -} - -impl FourierSeries { - pub fn random(k_max: usize, seed: u64) -> Self { - let mut rng = ChaCha8Rng::seed_from_u64(seed); - let mut coeffs: Vec = (0..=k_max) - .map(|_| Complex64::new(rng.gen::(), rng.gen::())) - .collect(); - let norm = coeffs.iter().map(|c| c.norm_sqr()).sum::().sqrt(); - for c in &mut coeffs { - *c /= norm; - } - Self { coeffs } - } - - pub fn eval(&self, x: f64) -> Complex64 { - self.coeffs - .iter() - .enumerate() - .map(|(k, c)| c * (Complex64::new(0.0, 2.0 * std::f64::consts::PI * k as f64 * x)).exp()) - .sum() - } - - /// Coefficient convolution: exact product series. - pub fn product(&self, other: &Self) -> Self { - let n = self.coeffs.len() + other.coeffs.len() - 1; - let mut coeffs = vec![Complex64::new(0.0, 0.0); n]; - for (i, a) in self.coeffs.iter().enumerate() { - for (j, b) in other.coeffs.iter().enumerate() { - coeffs[i + j] += a * b; - } - } - Self { coeffs } - } - - /// Exact QTT with bond dimension K+1, R sites of dim 2, MSB first. - pub fn to_qtt(&self, r: usize) -> anyhow::Result> { - anyhow::ensure!(r >= 2, "need r >= 2"); - let m = self.coeffs.len(); // K+1 - let phase = |k: usize, s: usize, n: usize| -> Complex64 { - let theta = 2.0 * std::f64::consts::PI * (k * s) as f64 / (1u64 << (n + 1)) as f64; - Complex64::new(0.0, theta).exp() - }; - let mut cores = Vec::with_capacity(r); - // first core: (1, 2, m), data[0 + 1*(s + 2*k)] - let mut d0 = vec![Complex64::new(0.0, 0.0); 2 * m]; - for k in 0..m { - for s in 0..2 { - d0[s + 2 * k] = self.coeffs[k] * phase(k, s, 0); - } - } - cores.push(tensor3_from_data(d0, 1, 2, m)?); - // middle cores n = 1..r-1: (m, 2, m), diagonal in k - for n in 1..r - 1 { - let mut d = vec![Complex64::new(0.0, 0.0); m * 2 * m]; - for k in 0..m { - for s in 0..2 { - d[k + m * (s + 2 * k)] = phase(k, s, n); - } - } - cores.push(tensor3_from_data(d, m, 2, m)?); - } - // last core: (m, 2, 1) - let mut dl = vec![Complex64::new(0.0, 0.0); m * 2]; - for k in 0..m { - for s in 0..2 { - dl[k + m * s] = phase(k, s, r - 1); - } - } - cores.push(tensor3_from_data(dl, m, 2, 1)?); - Ok(TensorTrain::new(cores)?) - } -} - -pub fn compress_svd( - tt: &mut TensorTrain, - tol: f64, - max_bond: usize, -) -> anyhow::Result<()> { - tt.compress(&CompressionOptions { - method: CompressionMethod::SVD, - tolerance: tol, - max_bond_dim: max_bond, - normalize_error: true, - })?; - Ok(()) -} -``` - -If `CompressionOptions` field names differ at the pinned rev, read `crates/tensor4all-simplett/src/compression.rs` and adjust; keep SVD method and relative tolerance semantics. - -- [ ] **Step 4: Run tests, verify pass** - -Run: `cargo test fourier` -Expected: 4 tests PASS. - -- [ ] **Step 5: Commit** - -```bash -git add -A && git commit -m "feat: random Fourier series with exact rank-(K+1) QTT construction" -``` - ---- - -### Task 3: Elementwise product algorithm wrappers - -**Files:** -- Create: `src/elementwise.rs` -- Modify: `src/lib.rs` (add `pub mod elementwise;`) - -**Interfaces:** -- Consumes: `fourier::{FourierSeries, compress_svd}`, `harness::{sample_grid_indices, index_to_bits}`. -- Produces: - ```rust - pub enum ElementwiseAlgo { Naive, Zipup, Fit, Aci } - pub fn elementwise_product( - algo: ElementwiseAlgo, - a: &TensorTrain, - b: &TensorTrain, - tol: f64, - max_bond: usize, - ) -> anyhow::Result>; - pub fn max_error_vs_series( - tt: &TensorTrain, exact: &FourierSeries, r: usize, n_samples: usize, seed: u64, - ) -> f64; - ``` - -Algorithm notes: -- Naive: direct core-wise Hadamard (bond Kronecker product) then SVD compression. This is the O(chi^4) baseline from the paper. Implemented locally, about 30 lines. -- Zipup and Fit: `tensor4all_treetn::hadamard` on bridged TreeTNs with `ContractionMethod::Zipup` / `::Fit`. Known upstream issue: Fit may converge to about 5e-4 relative error on elementwise products (documented in `tensor4all-itensorlike/tests/bug_fit_elementwise.rs`). Do NOT hide this: the fit arm gets a looser sanity bound (1e-3) and the report must mention the discrepancy. -- ACI: `tensor4all_aci::elementwise` with `|xs| xs[0] * xs[1]`. - -- [ ] **Step 1: Write failing test** - -```rust -#[cfg(test)] -mod tests { - use super::*; - use crate::fourier::{compress_svd, FourierSeries}; - - fn setup(r: usize, k: usize) -> (TensorTrain, TensorTrain, FourierSeries) { - let f = FourierSeries::random(k, 10); - let g = FourierSeries::random(k, 11); - let mut a = f.to_qtt(r).unwrap(); - let mut b = g.to_qtt(r).unwrap(); - compress_svd(&mut a, 1e-12, usize::MAX).unwrap(); - compress_svd(&mut b, 1e-12, usize::MAX).unwrap(); - (a, b, f.product(&g)) - } - - #[test] - fn all_algorithms_agree_with_exact_product() { - let r = 10; - let (a, b, exact) = setup(r, 6); - for (algo, bound) in [ - (ElementwiseAlgo::Naive, 1e-8), - (ElementwiseAlgo::Zipup, 1e-8), - (ElementwiseAlgo::Fit, 1e-3), - (ElementwiseAlgo::Aci, 1e-6), - ] { - let out = elementwise_product(algo, &a, &b, 1e-10, 200).unwrap(); - let err = max_error_vs_series(&out, &exact, r, 100, 5); - assert!(err < bound, "{algo:?}: err {err} exceeds {bound}"); - } - } -} -``` - -- [ ] **Step 2: Run test, verify failure** - -Run: `cargo test elementwise` -Expected: compile failure. - -- [ ] **Step 3: Implement** - -```rust -use num_complex::Complex64; -use tensor4all_simplett::{tensor3_from_data, AbstractTensorTrain, Tensor3Ops, TensorTrain}; - -use crate::fourier::{compress_svd, FourierSeries}; -use crate::harness::{index_to_bits, sample_grid_indices}; - -#[derive(Clone, Copy, Debug)] -pub enum ElementwiseAlgo { - Naive, - Zipup, - Fit, - Aci, -} - -pub fn elementwise_product( - algo: ElementwiseAlgo, - a: &TensorTrain, - b: &TensorTrain, - tol: f64, - max_bond: usize, -) -> anyhow::Result> { - match algo { - ElementwiseAlgo::Naive => hadamard_naive(a, b, tol, max_bond), - ElementwiseAlgo::Zipup => hadamard_treetn(a, b, tol, max_bond, false), - ElementwiseAlgo::Fit => hadamard_treetn(a, b, tol, max_bond, true), - ElementwiseAlgo::Aci => hadamard_aci(a, b, tol, max_bond), - } -} - -fn hadamard_naive( - a: &TensorTrain, - b: &TensorTrain, - tol: f64, - max_bond: usize, -) -> anyhow::Result> { - let mut cores = Vec::with_capacity(a.len()); - for (ca, cb) in a.site_tensors().iter().zip(b.site_tensors()) { - let (la, s, ra) = (ca.left_dim(), ca.site_dim(), ca.right_dim()); - let (lb, rb) = (cb.left_dim(), cb.right_dim()); - let mut data = vec![Complex64::new(0.0, 0.0); la * lb * s * ra * rb]; - for r2 in 0..rb { - for r1 in 0..ra { - for si in 0..s { - for l2 in 0..lb { - for l1 in 0..la { - let idx = (l1 + la * l2) + la * lb * (si + s * (r1 + ra * r2)); - data[idx] = ca.get3(l1, si, r1) * cb.get3(l2, si, r2); - } - } - } - } - } - cores.push(tensor3_from_data(data, la * lb, s, ra * rb)?); - } - let mut tt = TensorTrain::new(cores)?; - compress_svd(&mut tt, tol, max_bond)?; - Ok(tt) -} - -fn hadamard_treetn( - a: &TensorTrain, - b: &TensorTrain, - tol: f64, - max_bond: usize, - fit: bool, -) -> anyhow::Result> { - use tensor4all_core::SvdTruncationPolicy; - use tensor4all_treetn::contraction::{ContractionMethod, ContractionOptions}; - use tensor4all_treetn::{hadamard, tensor_train_to_treetn, treetn_to_tensor_train}; - - let (ta, ia) = tensor_train_to_treetn(a)?; - let (tb, ib) = tensor_train_to_treetn(b)?; - let pairs: Vec<_> = ia.into_iter().zip(ib.into_iter()).collect(); - let mut opts = ContractionOptions::default(); - opts.method = if fit { ContractionMethod::Fit } else { ContractionMethod::Zipup }; - opts.max_rank = Some(max_bond); - opts.svd_policy = SvdTruncationPolicy::new(tol); - let out = hadamard(&ta, &tb, &pairs, &0, opts) - .map_err(|e| anyhow::anyhow!("hadamard failed: {e:?}"))?; - Ok(treetn_to_tensor_train::(out)?) -} - -fn hadamard_aci( - a: &TensorTrain, - b: &TensorTrain, - tol: f64, - max_bond: usize, -) -> anyhow::Result> { - use tensor4all_aci::{elementwise, AciOptions}; - let opts = AciOptions:: { - tolerance: tol, - max_bond_dim: max_bond, - ..AciOptions::default() - }; - let res = elementwise(|xs: &[Complex64]| xs[0] * xs[1], &[a.clone(), b.clone()], &opts)?; - Ok(res.tensor_train) -} - -/// Max abs error against the exact product series at sampled grid points. -pub fn max_error_vs_series( - tt: &TensorTrain, - exact: &FourierSeries, - r: usize, - n_samples: usize, - seed: u64, -) -> f64 { - sample_grid_indices(r, n_samples, seed) - .iter() - .map(|&i| { - let x = i as f64 / (1u64 << r) as f64; - let v = tt.evaluate(&index_to_bits(i, r)).unwrap(); - (v - exact.eval(x)).norm() - }) - .fold(0.0, f64::max) - } -``` - -Exact field names of `ContractionOptions` (`max_rank` may be `usize` instead of `Option`, extra fields may exist) must be checked against `crates/tensor4all-treetn/src/treetn/contraction.rs` around line 854 at the pinned rev; adjust the two assignments, nothing else. If `hadamard`'s center-node type does not accept `&0`, use the first node name returned by the bridge. - -- [ ] **Step 4: Run test, verify pass** - -Run: `cargo test elementwise -- --nocapture` -Expected: PASS. If the Fit arm fails its 1e-3 bound, loosen to 1e-2 and record the measured value in a code comment referencing the upstream bug test. - -- [ ] **Step 5: Commit** - -```bash -git add -A && git commit -m "feat: four elementwise product algorithm wrappers with exact-series error metric" -``` - ---- - -### Task 4: Case 1 runner binary - -**Files:** -- Create: `src/bin/elementwise_fourier.rs` - -**Interfaces:** -- Consumes: everything from Tasks 1 to 3. -- Produces: JSON records named `elementwise_fourier--k.json` under `$OUT_DIR` (default `result/dev/raw`). Environment knobs: `BENCH_KS` (comma list, default `4,8,16,32,64`), `BENCH_R` (default 20), `BENCH_TOL` (default 1e-8), `BENCH_MAX_BOND` (default 4096), `BENCH_RUNS` (default 5), `BENCH_WARMUPS` (default 1), `BENCH_SEED` (default 0), `BENCH_ALGOS` (default `naive,zipup,fit,aci`), `OUT_DIR`. - -- [ ] **Step 1: Implement the runner** - -```rust -use num_complex::Complex64; -use std::path::PathBuf; -use t4a_bench::elementwise::{elementwise_product, max_error_vs_series, ElementwiseAlgo}; -use t4a_bench::fourier::{compress_svd, FourierSeries}; -use t4a_bench::harness::time_median; -use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; -use tensor4all_simplett::AbstractTensorTrain; - -fn env_or(key: &str, default: T) -> T { - std::env::var(key).ok().and_then(|v| v.parse().ok()).unwrap_or(default) -} - -fn parse_algo(s: &str) -> ElementwiseAlgo { - match s { - "naive" => ElementwiseAlgo::Naive, - "zipup" => ElementwiseAlgo::Zipup, - "fit" => ElementwiseAlgo::Fit, - "aci" => ElementwiseAlgo::Aci, - other => panic!("unknown algorithm {other}"), - } -} - -fn main() -> anyhow::Result<()> { - let ks: Vec = std::env::var("BENCH_KS") - .unwrap_or_else(|_| "4,8,16,32,64".into()) - .split(',') - .map(|s| s.trim().parse().unwrap()) - .collect(); - let r: usize = env_or("BENCH_R", 20); - let tol: f64 = env_or("BENCH_TOL", 1e-8); - let max_bond: usize = env_or("BENCH_MAX_BOND", 4096); - let runs: usize = env_or("BENCH_RUNS", 5); - let warmups: usize = env_or("BENCH_WARMUPS", 1); - let seed: u64 = env_or("BENCH_SEED", 0); - let algos: Vec = std::env::var("BENCH_ALGOS") - .unwrap_or_else(|_| "naive,zipup,fit,aci".into()) - .split(',') - .map(|s| s.trim().to_string()) - .collect(); - let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); - - let mut failures = Vec::new(); - for &k in &ks { - let f = FourierSeries::random(k, seed.wrapping_add(2 * k as u64)); - let g = FourierSeries::random(k, seed.wrapping_add(2 * k as u64 + 1)); - let exact = f.product(&g); - let mut a = f.to_qtt(r)?; - let mut b = g.to_qtt(r)?; - compress_svd(&mut a, tol, max_bond)?; - compress_svd(&mut b, tol, max_bond)?; - let input_chi = a.rank().max(b.rank()); - eprintln!("k_max={k} input_chi={input_chi}"); - - for algo_name in &algos { - let algo = parse_algo(algo_name); - let (out, timing) = time_median(warmups, runs, || { - elementwise_product(algo, &a, &b, tol, max_bond).expect("algorithm failed") - }); - let max_error = max_error_vs_series(&out, &exact, r, 256, seed.wrapping_add(999)); - // fit has a known upstream accuracy issue on elementwise products - let sanity = if matches!(algo, ElementwiseAlgo::Fit) { 1e-2 } else { 10.0 * tol }; - let rec = RunRecord { - schema_version: SCHEMA_VERSION, - case: "elementwise_fourier".into(), - algorithm: algo_name.clone(), - params: serde_json::json!({ - "k_max": k, "r": r, "input_max_bond_dim": input_chi, "max_bond": max_bond, - }), - seed, - tolerance: tol, - wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: out.rank(), - output_bond_dims: out.link_dims(), - }; - write_record(&out_dir, &format!("elementwise_fourier-{algo_name}-k{k}"), &rec)?; - eprintln!(" {algo_name}: t={:.4}s err={max_error:.2e} chi_out={}", timing.median_secs, out.rank()); - if max_error > sanity { - failures.push(format!("{algo_name} k={k}: err {max_error:.2e} > sanity {sanity:.2e}")); - } - } - } - if !failures.is_empty() { - anyhow::bail!("sanity failures:\n{}", failures.join("\n")); - } - Ok(()) -} -``` - -- [ ] **Step 2: Smoke run** - -```bash -BENCH_KS=4,8 BENCH_R=12 BENCH_RUNS=1 BENCH_WARMUPS=0 OUT_DIR=/tmp/t4abench-smoke cargo run --release --bin elementwise_fourier -``` - -Expected: exit 0, four JSON files per k in `/tmp/t4abench-smoke`, stderr shows per-algorithm time/error lines. Inspect one JSON for sane fields. - -- [ ] **Step 3: Commit** - -```bash -git add -A && git commit -m "feat: elementwise_fourier runner with env-configurable sweep and sanity gate" -``` - ---- - -### Task 5: HDF5 export and Julia correctness check (case 1) - -**Files:** -- Create: `src/hdf5_export.rs`, `julia/Project.toml`, `julia/check_elementwise.jl` -- Modify: `src/lib.rs` (add `pub mod hdf5_export;`), `src/bin/elementwise_fourier.rs` (export hook) - -**Interfaces:** -- Produces: `t4a_bench::hdf5_export::save_tt_as_mps(path: &str, name: &str, tt: &TensorTrain, append: bool) -> anyhow::Result<()>`. Runner env knob `EXPORT_HDF5=`: writes `instance-k.h5` containing MPS groups `f` and `g`, plus `instance-k.json` with the coefficient arrays. - -- [ ] **Step 1: Implement export module** - -```rust -use num_complex::Complex64; -use tensor4all_simplett::TensorTrain; -use tensor4all_treetn::tensor_train_to_treetn; - -pub fn save_tt_as_mps( - path: &str, - name: &str, - tt: &TensorTrain, - append: bool, -) -> anyhow::Result<()> { - let (treetn, _indices) = tensor_train_to_treetn(tt)?; - let itt = tensor4all_itensorlike::TensorTrain::from_treetn(treetn)?; - if append { - tensor4all_hdf5::append_mps(path, name, &itt)?; - } else { - tensor4all_hdf5::save_mps(path, name, &itt)?; - } - Ok(()) -} -``` - -Add a unit test in the same file: build `FourierSeries::random(3, 1).to_qtt(6)`, save to a temp file (`std::env::temp_dir()`), reload with `tensor4all_hdf5::load_mps`, assert `maxbonddim()` matches. This proves the Rust-side round trip; the Julia script proves cross-language. - -- [ ] **Step 2: Hook into the runner** - -In `src/bin/elementwise_fourier.rs`, inside the k loop after compressing `a` and `b`: - -```rust -if let Ok(dir) = std::env::var("EXPORT_HDF5") { - std::fs::create_dir_all(&dir)?; - let h5 = format!("{dir}/instance-k{k}.h5"); - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "f", &a, false)?; - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "g", &b, true)?; - let meta = serde_json::json!({ - "schema_version": 1, - "case": "elementwise_fourier", - "r": r, - "k_max": k, - "f_coeffs": f.coeffs.iter().map(|c| [c.re, c.im]).collect::>(), - "g_coeffs": g.coeffs.iter().map(|c| [c.re, c.im]).collect::>(), - }); - std::fs::write(format!("{dir}/instance-k{k}.json"), serde_json::to_string_pretty(&meta)?)?; -} -``` - -- [ ] **Step 3: Julia environment and check script** - -`julia/Project.toml`: - -```toml -[deps] -HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" -ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5" -ITensorMPS = "0d1a4710-d33b-49a5-8f18-73bdf49b47e2" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -``` - -`julia/check_elementwise.jl`: - -```julia -# Usage: julia --project=julia julia/check_elementwise.jl -# Reads instance-k.h5 (MPS groups "f","g") and instance-k.json, -# evaluates both MPS at sample grid points, compares to the analytic series. -using HDF5, ITensors, ITensorMPS, JSON3 - -dir, k = ARGS[1], ARGS[2] -meta = JSON3.read(read(joinpath(dir, "instance-k$k.json"), String)) -R = meta.r - -coeffs(v) = [complex(c[1], c[2]) for c in v] -series(c, x) = sum(c[j+1] * exp(2im * pi * j * x) for j in 0:length(c)-1) - -function eval_mps(psi::MPS, bits::Vector{Int}) - s = siteinds(psi) - v = ITensor(1.0) - for n in eachindex(psi) - v *= psi[n] * onehot(s[n] => bits[n] + 1) - end - return scalar(v) -end - -fails = 0 -h5open(joinpath(dir, "instance-k$k.h5"), "r") do file - for (name, cs) in (("f", coeffs(meta.f_coeffs)), ("g", coeffs(meta.g_coeffs))) - psi = read(file, name, MPS) - @assert length(psi) == R - for trial in 1:50 - i = rand(0:(2^R - 1)) - bits = [Int((i >> (R - n)) & 1) for n in 1:R] # MSB first - x = i / 2^R - got = eval_mps(psi, bits) - want = series(cs, x) - if abs(got - want) > 1e-6 - global fails += 1 - println("MISMATCH $name x=$x got=$got want=$want") - end - end - end -end -fails == 0 || error("$fails mismatches") -println("check_elementwise: OK") -``` - -- [ ] **Step 4: End-to-end verification** - -```bash -BENCH_KS=4 BENCH_R=10 BENCH_RUNS=1 BENCH_WARMUPS=0 OUT_DIR=/tmp/t4abench-h5 EXPORT_HDF5=/tmp/t4abench-h5 cargo run --release --bin elementwise_fourier -julia --project=julia -e 'using Pkg; Pkg.instantiate()' -julia --project=julia julia/check_elementwise.jl /tmp/t4abench-h5 4 -``` - -Expected: `check_elementwise: OK`. If ITensors cannot read complex MPS groups written by tensor4all-hdf5, check the `@type` attribute handling and consult `tensor4all-rs/docs/examples/julia/hdf5.jl` for the working read pattern. - -- [ ] **Step 5: Commit** - -```bash -git add -A && git commit -m "feat: ITensor-compatible HDF5 export and Julia cross-check for case 1" -``` - ---- - -### Task 6: Gaussian mixtures, analytic integral, quantics MPO construction - -**Files:** -- Create: `src/gaussian.rs` -- Modify: `src/lib.rs` (add `pub mod gaussian;`) - -**Interfaces:** -- Produces: - ```rust - pub struct GaussianMixture2D { pub weights: Vec, pub alphas: Vec, pub centers: Vec<(f64, f64)> } - impl GaussianMixture2D { - pub fn random(n: usize, box_l: f64, alpha_range: (f64, f64), seed: u64) -> Self; - pub fn eval(&self, x: f64, y: f64) -> f64; - } - /// closed form of int f(x,y) g(y,z) dy over the whole real line - pub fn analytic_contraction(f: &GaussianMixture2D, g: &GaussianMixture2D, x: f64, z: f64) -> f64; - /// f(v1, v2) as a quantics MPO: site n has (bit n of v1, bit n of v2), R sites - pub fn to_quantics_mpo(mix: &GaussianMixture2D, r: usize, box_l: f64, tol: f64, max_bond: usize) - -> anyhow::Result<(MPO, f64)>; // (mpo, grid_step) - pub fn grid_coord(i: u64, r: usize, box_l: f64) -> f64; // -L + i * 2L/2^R - ``` - -Math: a Gaussian `w exp(-a ((x-cx)^2 + (y-cy)^2))` factorizes over x and y, so -`int f_i(x,y) g_j(y,z) dy = w_i w_j e^{-a_i (x-cx_i)^2} e^{-b_j (z-cz_j)^2} sqrt(pi/(a_i+b_j)) exp(-(a_i b_j/(a_i+b_j)) (cy_i - cy_j)^2)`. -Random mixture: centers uniform in `[-L/2, L/2]^2` (kept away from the box edge so the tail truncation error stays small), weights U[0.5, 1.5], alphas log-uniform in `alpha_range`. - -MPO construction: build a fused 2D quantics TT with `quanticscrossinterpolate` on `DiscretizedGrid::builder(&[r, r]).with_lower_bound(&[-L, -L]).with_upper_bound(&[L, L]).with_unfolding_scheme(UnfoldingScheme::Fused).build()`, then reinterpret each dim-4 site core `(l, 4, rdim)` as a `Tensor4` `(l, 2, 2, rdim)` with the SAME column-major buffer. Per quanticsgrids fused convention the fused local index is `bit(var1) + 2*bit(var2)` with var order to be confirmed by the unit test below; if the evaluation test fails, transpose the two site legs (swap `s1`/`s2` when copying, index `l + L*(s1 + 2*(s2 + 2*r))`). - -- [ ] **Step 1: Write failing tests** - -```rust -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn analytic_contraction_matches_quadrature() { - let f = GaussianMixture2D::random(3, 4.0, (0.5, 2.0), 1); - let g = GaussianMixture2D::random(2, 4.0, (0.5, 2.0), 2); - let (x, z) = (0.3, -0.7); - // trapezoid quadrature over y in [-8, 8] - let n = 20_000; - let (lo, hi) = (-8.0, 8.0); - let h = (hi - lo) / n as f64; - let mut s = 0.0; - for i in 0..=n { - let y = lo + i as f64 * h; - let w = if i == 0 || i == n { 0.5 } else { 1.0 }; - s += w * f.eval(x, y) * g.eval(y, z) * h; - } - let a = analytic_contraction(&f, &g, x, z); - assert!((s - a).abs() < 1e-8 * a.abs().max(1.0), "quad {s} vs analytic {a}"); - } - - #[test] - fn quantics_mpo_evaluates_to_function_values() { - let r = 8; - let l = 4.0; - let mix = GaussianMixture2D::random(3, l, (0.5, 2.0), 3); - let (mpo, _dy) = to_quantics_mpo(&mix, r, l, 1e-10, 200).unwrap(); - assert_eq!(mpo.len(), r); - for &(i, j) in &[(0u64, 0u64), (37, 200), (255, 1), (128, 128)] { - let x = grid_coord(i, r, l); - let y = grid_coord(j, r, l); - let xb = crate::harness::index_to_bits(i, r); - let yb = crate::harness::index_to_bits(j, r); - let mut idx = Vec::with_capacity(2 * r); - for n in 0..r { - idx.push(xb[n]); - idx.push(yb[n]); - } - let v = mpo.evaluate(&idx).unwrap(); - assert!((v - mix.eval(x, y)).abs() < 1e-6, "at ({x},{y}): {v} vs {}", mix.eval(x, y)); - } - } -} -``` - -- [ ] **Step 2: Run tests, verify failure** - -Run: `cargo test gaussian` -Expected: compile failure. - -- [ ] **Step 3: Implement** - -```rust -use rand::Rng; -use rand::SeedableRng; -use rand_chacha::ChaCha8Rng; -use tensor4all_simplett::mpo::{tensor4_from_data, MPO}; -use tensor4all_simplett::{AbstractTensorTrain, Tensor3Ops}; -use tensor4all_quanticstci::{quanticscrossinterpolate, DiscretizedGrid, QtciOptions, UnfoldingScheme}; - -#[derive(Clone, Debug)] -pub struct GaussianMixture2D { - pub weights: Vec, - pub alphas: Vec, - pub centers: Vec<(f64, f64)>, -} - -impl GaussianMixture2D { - pub fn random(n: usize, box_l: f64, alpha_range: (f64, f64), seed: u64) -> Self { - let mut rng = ChaCha8Rng::seed_from_u64(seed); - let half = box_l / 2.0; - let (a_lo, a_hi) = alpha_range; - let mut weights = Vec::new(); - let mut alphas = Vec::new(); - let mut centers = Vec::new(); - for _ in 0..n { - weights.push(rng.gen_range(0.5..1.5)); - alphas.push((rng.gen_range(a_lo.ln()..a_hi.ln())).exp()); - centers.push((rng.gen_range(-half..half), rng.gen_range(-half..half))); - } - Self { weights, alphas, centers } - } - - pub fn eval(&self, x: f64, y: f64) -> f64 { - (0..self.weights.len()) - .map(|i| { - let (cx, cy) = self.centers[i]; - self.weights[i] * (-self.alphas[i] * ((x - cx).powi(2) + (y - cy).powi(2))).exp() - }) - .sum() - } -} - -pub fn analytic_contraction(f: &GaussianMixture2D, g: &GaussianMixture2D, x: f64, z: f64) -> f64 { - let mut s = 0.0; - for i in 0..f.weights.len() { - let (fcx, fcy) = f.centers[i]; - let a = f.alphas[i]; - let fx = f.weights[i] * (-a * (x - fcx).powi(2)).exp(); - for j in 0..g.weights.len() { - let (gcy, gcz) = g.centers[j]; - let b = g.alphas[j]; - let gz = g.weights[j] * (-b * (z - gcz).powi(2)).exp(); - let ab = a + b; - let yfac = (std::f64::consts::PI / ab).sqrt() * (-(a * b / ab) * (fcy - gcy).powi(2)).exp(); - s += fx * gz * yfac; - } - } - s -} - -pub fn grid_coord(i: u64, r: usize, box_l: f64) -> f64 { - let step = 2.0 * box_l / (1u64 << r) as f64; - -box_l + i as f64 * step -} - -pub fn to_quantics_mpo( - mix: &GaussianMixture2D, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, -) -> anyhow::Result<(MPO, f64)> { - let grid = DiscretizedGrid::builder(&[r, r]) - .with_lower_bound(&[-box_l, -box_l]) - .with_upper_bound(&[box_l, box_l]) - .with_unfolding_scheme(UnfoldingScheme::Fused) - .build()?; - let m = mix.clone(); - let opts = QtciOptions::default() - .with_tolerance(tol) - .with_maxbonddim(max_bond) - .with_unfoldingscheme(UnfoldingScheme::Fused); - let (qtci, _ranks, _errs) = quanticscrossinterpolate(&grid, move |xy: &[f64]| m.eval(xy[0], xy[1]), None, opts)?; - let tt = qtci.tensor_train(); - let mut cores4 = Vec::with_capacity(tt.len()); - for c in tt.site_tensors() { - let (l, s, rd) = (c.left_dim(), c.site_dim(), c.right_dim()); - anyhow::ensure!(s == 4, "expected fused site dim 4, got {s}"); - // fused index assumed s = s1 + 2*s2 (var1 bit least significant). - // If quantics_mpo_evaluates_to_function_values fails, swap s1 and s2 here. - let mut data = vec![0.0f64; l * 4 * rd]; - for rr in 0..rd { - for s2 in 0..2 { - for s1 in 0..2 { - for ll in 0..l { - let fused = s1 + 2 * s2; - data[ll + l * (s1 + 2 * (s2 + 2 * rr))] = c.get3(ll, fused, rr); - } - } - } - } - cores4.push(tensor4_from_data(data, l, 2, 2, rd)?); - } - let step = 2.0 * box_l / (1u64 << r) as f64; - Ok((MPO::new(cores4)?, step)) -} -``` - -Note the identity copy: with fused = s1 + 2*s2 the Tensor4 column-major layout equals the Tensor3 layout, but write the explicit loop anyway, it makes the swap fallback a one-line change. If the fused variable order turns out reversed (test failure), change `let fused = s1 + 2 * s2;` to `let fused = s2 + 2 * s1;` and re-run. - -- [ ] **Step 4: Run tests, verify pass** - -Run: `cargo test gaussian -- --nocapture` -Expected: both tests PASS (TCI on a 3-Gaussian mixture at R=8 runs in seconds). - -- [ ] **Step 5: Commit** - -```bash -git add -A && git commit -m "feat: 2D Gaussian mixtures with analytic y-integral and quantics MPO construction" -``` - ---- - -### Task 7: MPO-MPO contraction wrappers and case 2 runner - -**Files:** -- Create: `src/mpo_contract.rs`, `src/bin/mpo_mpo_quantics.rs` -- Modify: `src/lib.rs` (add `pub mod mpo_contract;`) - -**Interfaces:** -- Consumes: `gaussian::*`, `harness::*`, `record::*`. -- Produces: - ```rust - pub enum MpoAlgo { Naive, Zipup, Fit } - pub fn mpo_contract(algo: MpoAlgo, a: &MPO, b: &MPO, tol: f64, max_bond: usize) - -> anyhow::Result>; - pub fn max_rel_error_vs_analytic( - h: &MPO, dy: f64, f: &GaussianMixture2D, g: &GaussianMixture2D, - r: usize, box_l: f64, n_samples: usize, seed: u64, - ) -> f64; - ``` -- Runner env knobs: `BENCH_RS` (default `10,12,14,16`), `BENCH_NGAUSS` (default 8), `BENCH_BOX_L` (default 6.0), `BENCH_ALPHA_LO`/`BENCH_ALPHA_HI` (default 0.5/8.0), `BENCH_TOL` (1e-8), `BENCH_MAX_BOND` (512), `BENCH_RUNS` (5), `BENCH_WARMUPS` (1), `BENCH_SEED` (0), `BENCH_ALGOS` (`naive,zipup,fit`), `BENCH_SANITY` (default 1e-4), `OUT_DIR`, `EXPORT_HDF5`. - -- [ ] **Step 1: Write failing test for wrappers** - -In `src/mpo_contract.rs`: - -```rust -#[cfg(test)] -mod tests { - use super::*; - use crate::gaussian::{to_quantics_mpo, GaussianMixture2D}; - - #[test] - fn all_algorithms_agree_with_analytic_integral() { - let (r, l) = (8, 6.0); - let f = GaussianMixture2D::random(3, l, (0.5, 2.0), 20); - let g = GaussianMixture2D::random(3, l, (0.5, 2.0), 21); - let (fa, dy) = to_quantics_mpo(&f, r, l, 1e-10, 200).unwrap(); - let (gb, _) = to_quantics_mpo(&g, r, l, 1e-10, 200).unwrap(); - for algo in [MpoAlgo::Naive, MpoAlgo::Zipup, MpoAlgo::Fit] { - let h = mpo_contract(algo, &fa, &gb, 1e-10, 400).unwrap(); - let err = max_rel_error_vs_analytic(&h, dy, &f, &g, r, l, 50, 22); - // R=8 discretization floor dominates; bound is loose on purpose - assert!(err < 1e-2, "{algo:?}: rel err {err}"); - } - } -} -``` - -- [ ] **Step 2: Run test, verify failure** - -Run: `cargo test mpo_contract` -Expected: compile failure. - -- [ ] **Step 3: Implement wrappers** - -```rust -use tensor4all_simplett::mpo::{ - contract_fit, contract_naive, contract_zipup, ContractionOptions, FitOptions, MPO, -}; - -use crate::gaussian::{analytic_contraction, grid_coord, GaussianMixture2D}; -use crate::harness::{index_to_bits, sample_grid_indices}; - -#[derive(Clone, Copy, Debug)] -pub enum MpoAlgo { - Naive, - Zipup, - Fit, -} - -pub fn mpo_contract( - algo: MpoAlgo, - a: &MPO, - b: &MPO, - tol: f64, - max_bond: usize, -) -> anyhow::Result> { - let opts = ContractionOptions { - tolerance: tol, - max_bond_dim: max_bond, - ..ContractionOptions::default() - }; - let out = match algo { - MpoAlgo::Naive => contract_naive(a, b, Some(opts))?, - MpoAlgo::Zipup => contract_zipup(a, b, &opts)?, - MpoAlgo::Fit => { - let fopts = FitOptions { - tolerance: tol, - max_bond_dim: max_bond, - ..FitOptions::default() - }; - contract_fit(a, b, &fopts, None)? - } - }; - Ok(out) -} - -/// Relative max error of h(x,z)*... vs the analytic integral, normalized by -/// the max sampled |analytic| value. The MPO already contains the plain sum -/// over the y grid, so multiply by dy to approximate the integral. -pub fn max_rel_error_vs_analytic( - h: &MPO, - dy: f64, - f: &GaussianMixture2D, - g: &GaussianMixture2D, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> f64 { - let xs = sample_grid_indices(r, n_samples, seed); - let zs = sample_grid_indices(r, n_samples, seed.wrapping_add(1)); - let mut max_abs = 0.0f64; - let mut max_ref = 0.0f64; - for (&ix, &iz) in xs.iter().zip(&zs) { - let x = grid_coord(ix, r, box_l); - let z = grid_coord(iz, r, box_l); - let xb = index_to_bits(ix, r); - let zb = index_to_bits(iz, r); - let mut idx = Vec::with_capacity(2 * r); - for n in 0..r { - idx.push(xb[n]); - idx.push(zb[n]); - } - let got = h.evaluate(&idx).unwrap() * dy; - let want = analytic_contraction(f, g, x, z); - max_abs = max_abs.max((got - want).abs()); - max_ref = max_ref.max(want.abs()); - } - max_abs / max_ref.max(f64::MIN_POSITIVE) -} -``` - -If `ContractionOptions` or `FitOptions` field names differ at the pinned rev, read `crates/tensor4all-simplett/src/mpo/options.rs` (or wherever they live) and adjust only the struct literals. - -- [ ] **Step 4: Run test, verify pass** - -Run: `cargo test mpo_contract -- --nocapture` -Expected: PASS. - -- [ ] **Step 5: Implement the runner** - -`src/bin/mpo_mpo_quantics.rs`, same skeleton as the case 1 runner: - -```rust -use std::path::PathBuf; -use t4a_bench::gaussian::{to_quantics_mpo, GaussianMixture2D}; -use t4a_bench::harness::time_median; -use t4a_bench::mpo_contract::{max_rel_error_vs_analytic, mpo_contract, MpoAlgo}; -use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; - -fn env_or(key: &str, default: T) -> T { - std::env::var(key).ok().and_then(|v| v.parse().ok()).unwrap_or(default) -} - -fn main() -> anyhow::Result<()> { - let rs: Vec = std::env::var("BENCH_RS") - .unwrap_or_else(|_| "10,12,14,16".into()) - .split(',').map(|s| s.trim().parse().unwrap()).collect(); - let ngauss: usize = env_or("BENCH_NGAUSS", 8); - let box_l: f64 = env_or("BENCH_BOX_L", 6.0); - let alpha_lo: f64 = env_or("BENCH_ALPHA_LO", 0.5); - let alpha_hi: f64 = env_or("BENCH_ALPHA_HI", 8.0); - let tol: f64 = env_or("BENCH_TOL", 1e-8); - let max_bond: usize = env_or("BENCH_MAX_BOND", 512); - let runs: usize = env_or("BENCH_RUNS", 5); - let warmups: usize = env_or("BENCH_WARMUPS", 1); - let seed: u64 = env_or("BENCH_SEED", 0); - let sanity: f64 = env_or("BENCH_SANITY", 1e-4); - let algos: Vec = std::env::var("BENCH_ALGOS") - .unwrap_or_else(|_| "naive,zipup,fit".into()) - .split(',').map(|s| s.trim().to_string()).collect(); - let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); - - let f = GaussianMixture2D::random(ngauss, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(1)); - let g = GaussianMixture2D::random(ngauss, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(2)); - - let mut failures = Vec::new(); - for &r in &rs { - let (fa, dy) = to_quantics_mpo(&f, r, box_l, tol, max_bond)?; - let (gb, _) = to_quantics_mpo(&g, r, box_l, tol, max_bond)?; - let input_chi = fa.rank().max(gb.rank()); - eprintln!("r={r} input_chi={input_chi}"); - - for algo_name in &algos { - let algo = match algo_name.as_str() { - "naive" => MpoAlgo::Naive, - "zipup" => MpoAlgo::Zipup, - "fit" => MpoAlgo::Fit, - other => panic!("unknown algorithm {other}"), - }; - let (h, timing) = time_median(warmups, runs, || { - mpo_contract(algo, &fa, &gb, tol, max_bond).expect("contraction failed") - }); - let max_error = max_rel_error_vs_analytic(&h, dy, &f, &g, r, box_l, 128, seed.wrapping_add(99)); - let rec = RunRecord { - schema_version: SCHEMA_VERSION, - case: "mpo_mpo_quantics".into(), - algorithm: algo_name.clone(), - params: serde_json::json!({ - "r": r, "n_gauss": ngauss, "box_l": box_l, - "alpha_range": [alpha_lo, alpha_hi], "max_bond": max_bond, - }), - seed, - tolerance: tol, - wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: h.rank(), - output_bond_dims: h.link_dims(), - }; - write_record(&out_dir, &format!("mpo_mpo_quantics-{algo_name}-r{r}"), &rec)?; - eprintln!(" {algo_name}: t={:.4}s rel_err={max_error:.2e} chi_out={}", timing.median_secs, h.rank()); - if max_error > sanity { - failures.push(format!("{algo_name} r={r}: rel err {max_error:.2e} > {sanity:.2e}")); - } - } - } - if !failures.is_empty() { - anyhow::bail!("sanity failures:\n{}", failures.join("\n")); - } - Ok(()) -} -``` - -Note: `MPO::rank()` and `link_dims()` are inherent methods; if names differ at the pin, check `crates/tensor4all-simplett/src/mpo/mpo.rs`. The sanity bound default 1e-4 accounts for the discretization floor at moderate R; the report shows the actual error curve. - -- [ ] **Step 6: Smoke run** - -```bash -BENCH_RS=8,10 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 OUT_DIR=/tmp/t4abench-mpo cargo run --release --bin mpo_mpo_quantics -``` - -Expected: exit 0, six JSON files, plausible errors that shrink from r=8 to r=10. - -- [ ] **Step 7: Commit** - -```bash -git add -A && git commit -m "feat: MPO-MPO contraction wrappers and mpo_mpo_quantics runner" -``` - ---- - -### Task 8: Case 2 HDF5 export and Julia check - -**Files:** -- Modify: `src/hdf5_export.rs`, `src/bin/mpo_mpo_quantics.rs` -- Create: `julia/check_mpo_mpo.jl` - -**Interfaces:** -- Produces: `hdf5_export::save_fused_tt_as_mps(path, name, tt: &TensorTrain, append: bool)`, same bridge as case 1 but for `f64`. The runner exports the FUSED site-dim-4 TT (before Tensor4 conversion) so `save_mps` applies directly, plus `instance-r.json` with mixture parameters. - -- [ ] **Step 1: Generalize the export function** - -Make `save_tt_as_mps` generic: - -```rust -pub fn save_tt_as_mps( - path: &str, - name: &str, - tt: &tensor4all_simplett::TensorTrain, - append: bool, -) -> anyhow::Result<()> -where - T: tensor4all_simplett::TTScalar, - // add whatever bounds tensor_train_to_treetn requires; check its signature at the pin -{ - let (treetn, _indices) = tensor_train_to_treetn(tt)?; - let itt = tensor4all_itensorlike::TensorTrain::from_treetn(treetn)?; - if append { - tensor4all_hdf5::append_mps(path, name, &itt)?; - } else { - tensor4all_hdf5::save_mps(path, name, &itt)?; - } - Ok(()) -} -``` - -To export the fused TT, `to_quantics_mpo` must also return it (or add a sibling `to_quantics_fused_tt` returning `TensorTrain`; prefer the sibling, it keeps interfaces stable). Update `src/gaussian.rs`: extract the qtci call into `pub fn to_quantics_fused_tt(mix, r, box_l, tol, max_bond) -> anyhow::Result>` and have `to_quantics_mpo` call it. Existing tests must still pass unchanged. - -- [ ] **Step 2: Hook into the runner** - -Inside the r loop, mirroring case 1: - -```rust -if let Ok(dir) = std::env::var("EXPORT_HDF5") { - std::fs::create_dir_all(&dir)?; - let h5 = format!("{dir}/instance-r{r}.h5"); - let ftt = t4a_bench::gaussian::to_quantics_fused_tt(&f, r, box_l, tol, max_bond)?; - let gtt = t4a_bench::gaussian::to_quantics_fused_tt(&g, r, box_l, tol, max_bond)?; - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "f", &ftt, false)?; - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "g", >t, true)?; - let meta = serde_json::json!({ - "schema_version": 1, "case": "mpo_mpo_quantics", "r": r, "box_l": box_l, - "f": {"weights": f.weights, "alphas": f.alphas, "centers": f.centers}, - "g": {"weights": g.weights, "alphas": g.alphas, "centers": g.centers}, - }); - std::fs::write(format!("{dir}/instance-r{r}.json"), serde_json::to_string_pretty(&meta)?)?; -} -``` - -- [ ] **Step 3: Julia check script** - -`julia/check_mpo_mpo.jl`: loads the two MPS (site dim 4), evaluates at random fused grid indices, compares to the mixture formula: - -```julia -# Usage: julia --project=julia julia/check_mpo_mpo.jl -using HDF5, ITensors, ITensorMPS, JSON3 - -dir, rstr = ARGS[1], ARGS[2] -R = parse(Int, rstr) -meta = JSON3.read(read(joinpath(dir, "instance-r$rstr.json"), String)) -L = meta.box_l - -function mixture(m, x, y) - s = 0.0 - for i in eachindex(m.weights) - cx, cy = m.centers[i] - s += m.weights[i] * exp(-m.alphas[i] * ((x - cx)^2 + (y - cy)^2)) - end - return s -end - -coord(i) = -L + i * 2L / 2^R - -function eval_mps(psi::MPS, locals::Vector{Int}) - s = siteinds(psi) - v = ITensor(1.0) - for n in eachindex(psi) - v *= psi[n] * onehot(s[n] => locals[n] + 1) - end - return scalar(v) -end - -fails = 0 -h5open(joinpath(dir, "instance-r$rstr.h5"), "r") do file - for (name, m) in (("f", meta.f), ("g", meta.g)) - psi = read(file, name, MPS) - @assert length(psi) == R - for trial in 1:50 - ix, iy = rand(0:2^R-1), rand(0:2^R-1) - xb = [Int((ix >> (R - n)) & 1) for n in 1:R] - yb = [Int((iy >> (R - n)) & 1) for n in 1:R] - fused = [xb[n] + 2 * yb[n] for n in 1:R] # matches Rust s1 + 2*s2; swap if mismatched - got = eval_mps(psi, fused) - want = mixture(m, coord(ix), coord(iy)) - if abs(got - want) > 1e-5 * max(1.0, abs(want)) - global fails += 1 - println("MISMATCH $name ($(coord(ix)), $(coord(iy))): $got vs $want") - end - end - end -end -fails == 0 || error("$fails mismatches") -println("check_mpo_mpo: OK") -``` - -The fused-order comment mirrors the Rust-side fallback: whichever variant made the Rust test pass, use the same here. - -- [ ] **Step 4: End-to-end verification** - -```bash -BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 OUT_DIR=/tmp/t4abench-mpo-h5 EXPORT_HDF5=/tmp/t4abench-mpo-h5 cargo run --release --bin mpo_mpo_quantics -julia --project=julia julia/check_mpo_mpo.jl /tmp/t4abench-mpo-h5 8 -``` - -Expected: `check_mpo_mpo: OK`. - -- [ ] **Step 5: Run full test suite, commit** - -```bash -cargo test -git add -A && git commit -m "feat: case 2 HDF5 export and Julia cross-check" -``` - ---- - -### Task 9: Report generator and run script - -**Files:** -- Create: `pyproject.toml`, `scripts/report.py`, `scripts/run_all.sh` - -**Interfaces:** -- Consumes: `RunRecord` JSON files in `result//raw/`. -- Produces: `result//.md` with a summary table, fitted scaling exponents, and two SVG plots per case (`-time.svg`, `-error.svg`); `result//run.yaml` metadata. - -- [ ] **Step 1: pyproject.toml** - -```toml -[project] -name = "t4a-bench-report" -version = "0.1.0" -requires-python = ">=3.11" -dependencies = ["matplotlib>=3.8", "numpy>=1.26"] -``` - -- [ ] **Step 2: scripts/report.py** - -```python -#!/usr/bin/env python3 -"""Render Markdown reports and SVG scaling plots from RunRecord JSON files. - -Usage: uv run scripts/report.py result/ -""" -import json -import sys -from collections import defaultdict -from pathlib import Path - -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import numpy as np - -X_AXIS = { - # case name -> (record field used as x, axis label) - "elementwise_fourier": ("input_max_bond_dim", "input bond dimension chi"), - "mpo_mpo_quantics": ("input_max_bond_dim", "input bond dimension chi"), -} - - -def load(profile_dir: Path): - cases = defaultdict(lambda: defaultdict(list)) - for path in sorted((profile_dir / "raw").glob("*.json")): - rec = json.loads(path.read_text()) - assert rec["schema_version"] == 1, f"unknown schema in {path}" - cases[rec["case"]][rec["algorithm"]].append(rec) - return cases - - -def fit_exponent(xs, ys): - xs, ys = np.asarray(xs, float), np.asarray(ys, float) - mask = (xs > 0) & (ys > 0) - if mask.sum() < 2: - return float("nan") - p = np.polyfit(np.log(xs[mask]), np.log(ys[mask]), 1) - return p[0] - - -def render_case(case, algos, profile_dir: Path): - xfield, xlabel = X_AXIS[case] - lines = [f"# {case}", "", "| algorithm | points | fitted time exponent | worst error |", - "|---|---|---|---|"] - fig_t, ax_t = plt.subplots(figsize=(5, 4)) - fig_e, ax_e = plt.subplots(figsize=(5, 4)) - for algo, recs in sorted(algos.items()): - recs = sorted(recs, key=lambda rec: rec[xfield]) - xs = [rec[xfield] for rec in recs] - ts = [rec["wall_time_median_secs"] for rec in recs] - es = [rec["max_error"] for rec in recs] - expo = fit_exponent(xs, ts) - lines.append(f"| {algo} | {len(recs)} | {expo:.2f} | {max(es):.2e} |") - ax_t.loglog(xs, ts, "o-", label=f"{algo} (chi^{expo:.1f})") - ax_e.loglog(xs, es, "o-", label=algo) - for ax, ylab in ((ax_t, "median wall time [s]"), (ax_e, "max error")): - ax.set_xlabel(xlabel) - ax.set_ylabel(ylab) - ax.legend() - ax.grid(True, which="both", alpha=0.3) - fig_t.tight_layout() - fig_e.tight_layout() - fig_t.savefig(profile_dir / f"{case}-time.svg") - fig_e.savefig(profile_dir / f"{case}-error.svg") - lines += ["", f"![time](./{case}-time.svg)", "", f"![error](./{case}-error.svg)", ""] - (profile_dir / f"{case}.md").write_text("\n".join(lines)) - print(f"wrote {profile_dir / (case + '.md')}") - - -def main(): - profile_dir = Path(sys.argv[1]) - cases = load(profile_dir) - if not cases: - sys.exit(f"no records under {profile_dir}/raw") - for case, algos in cases.items(): - render_case(case, algos, profile_dir) - - -if __name__ == "__main__": - main() -``` - -- [ ] **Step 3: scripts/run_all.sh** - -```bash -#!/usr/bin/env bash -# Usage: scripts/run_all.sh (e.g. mac-cpu) -set -euo pipefail -PROFILE="${1:?usage: run_all.sh }" -ROOT="$(cd "$(dirname "$0")/.." && pwd)" -OUT="$ROOT/result/$PROFILE" -mkdir -p "$OUT/raw" - -cargo build --release - -OUT_DIR="$OUT/raw" cargo run --release --bin elementwise_fourier -OUT_DIR="$OUT/raw" cargo run --release --bin mpo_mpo_quantics - -cat > "$OUT/run.yaml" < - BENCH_KS=4 BENCH_R=10 BENCH_RUNS=1 BENCH_WARMUPS=0 - OUT_DIR=/tmp/smoke EXPORT_HDF5=/tmp/smoke - cargo run --release --bin elementwise_fourier - - name: smoke mpo - run: > - BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 - OUT_DIR=/tmp/smoke cargo run --release --bin mpo_mpo_quantics - - uses: julia-actions/setup-julia@v2 - with: - version: "1" - - name: julia check - run: | - julia --project=julia -e 'using Pkg; Pkg.instantiate()' - julia --project=julia julia/check_elementwise.jl /tmp/smoke 4 -``` - -- [ ] **Step 3: Full local verification** - -```bash -cargo test --release -BENCH_KS=4 BENCH_R=10 BENCH_RUNS=1 BENCH_WARMUPS=0 OUT_DIR=/tmp/final-smoke EXPORT_HDF5=/tmp/final-smoke cargo run --release --bin elementwise_fourier -BENCH_RS=8 BENCH_NGAUSS=3 BENCH_RUNS=1 BENCH_WARMUPS=0 BENCH_SANITY=1e-1 OUT_DIR=/tmp/final-smoke cargo run --release --bin mpo_mpo_quantics -julia --project=julia julia/check_elementwise.jl /tmp/final-smoke 4 -julia --project=julia julia/check_mpo_mpo.jl /tmp/final-smoke 8 -``` - -Expected: everything green. - -- [ ] **Step 4: Commit** - -```bash -git add -A && git commit -m "docs: README, MIT license, CI workflow" -``` - ---- - -### Task 11 (manual, after review): first real run and publication - -Not for a subagent; the user decides when. - -- [ ] Run `scripts/run_all.sh mac-cpu` with full sweeps (default env), inspect reports, commit `result/mac-cpu/`. -- [ ] Create the public GitHub repo `tensor4all/tensor4all-benchmark` and push (`gh repo create tensor4all/tensor4all-benchmark --public --source . --push`). Requires user confirmation. - -## Self-review notes - -- Spec coverage: layout (Task 1), case 1 (Tasks 2 to 5), case 2 (Tasks 6 to 8), results workflow (Task 9), README/CI (Task 10), first committed results (Task 11). The spec's `benches/` directory became `src/bin/`, a deliberate simplification recorded here. -- Known uncertainty is confined to exact upstream option-struct field names at the pinned rev; each affected step names the exact source file to consult and limits the allowed adjustment. -- The treetn hadamard path for case 1 zipup/fit and the fused-order question in case 2 both carry explicit test-first fallbacks. diff --git a/docs/superpowers/specs/2026-08-04-tensor4all-benchmark-design.md b/docs/superpowers/specs/2026-08-04-tensor4all-benchmark-design.md deleted file mode 100644 index d81ecff..0000000 --- a/docs/superpowers/specs/2026-08-04-tensor4all-benchmark-design.md +++ /dev/null @@ -1,155 +0,0 @@ -# tensor4all-benchmark design - -Date: 2026-08-04 -Status: draft for review - -## Purpose - -Public repository (`github.com/tensor4all/tensor4all-benchmark`, MIT) serving as an -open experimentation ground for comparing tensor-network contraction algorithms -implemented in tensor4all-rs. Primary audience: ourselves and third parties who want -reproducible algorithm comparisons (fitting vs zipup vs ACI vs naive) on well-defined -problem instances. It is not a low-level kernel benchmark (that is tenferro-benchmark) -and not a cross-framework showdown. - -## Scope of the initial version - -Two benchmark cases, implemented in this order: - -1. **Elementwise multiplication of random Fourier series (QTT)**, following the setup - of Ritter, arXiv:2604.00037 (ACI paper). -2. **General MPO-MPO contraction on 2D quantics Gaussians**, with an analytically - known result. - -Out of scope for the initial version: GPU, TreeTN beyond a possible same-problem run -in case 2, cross-language performance comparison (Julia is used for correctness -reference only), CI-based full measurement runs. - -## Stack and repository layout - -Cargo workspace, standalone repository. tensor4all-rs is consumed as a pinned git -dependency (switch to crates.io versions once published). Report generation in Python -managed by uv. Modeled on tenferro-benchmark but smaller. - -``` -tensor4all-benchmark/ - README.md # purpose, latest result summary, links to reports - Cargo.toml # workspace, tensor4all-rs pinned via git - src/ # shared: problem generators, timing harness, JSON schema - benches/elementwise_fourier/ # case 1 runner (binary, not criterion) - benches/mpo_mpo_quantics/ # case 2 runner - julia/ # Julia reference implementation for correctness checks - scripts/ # run_all.sh, uv Python: JSON -> Markdown report + SVG plots - result// # latest committed reports; history lives in git - docs/ -``` - -Runners are plain binaries emitting JSON (one file per run, schema versioned), not -criterion benches: we need custom sweeps, error metrics, and rank reporting. - -## Case 1: elementwise multiplication, random Fourier series - -Problem definition (per arXiv:2604.00037): - -- Two band-limited random Fourier series on [0,1), K+1 modes each. Complex - coefficients with real and imaginary parts drawn independently from U[0,1], - normalized so that sum_k |g_k|^2 = 1. Fixed RNG seed per instance; the same - instance is fed to every algorithm. -- Each series is represented as a QTT (R bits, resolution 2^R chosen large enough - that the series is exactly representable up to numerical precision). Band limit - implies QTT bond dimension chi in O(sqrt(K)). -- Task: compute the elementwise product as a QTT to tolerance tau (default 1e-8). - -Sweep: K over a geometric grid (thus chi from ~10 to ~few hundred, machine -permitting). - -Algorithms (all from tensor4all-rs): - -- naive contraction + SVD truncation (baseline, O(chi^4)) -- zipup (tensor4all-simplett) -- fitting / variational (tensor4all-itensorlike / simplett fit) -- ACI (tensor4all-aci) - -Measured per (algorithm, K, seed): - -- wall time (median of N repeats, N configurable, warmup separate) -- output bond dimension profile (max and per-bond) -- max error against the exact product, evaluated via the exact Fourier - coefficients of the product series (convolution of the input coefficient - vectors), sampled on a fixed set of points -- fitted scaling exponent of time vs chi reported in the summary - -## Case 2: MPO-MPO contraction, 2D quantics Gaussians - -Problem definition: - -- f(x,y) = sum_i a_i exp(-alpha_i |(x,y) - r_i|^2), a random mixture of Gaussians - (positions, weights, widths drawn with a fixed seed; count and width range are - sweep parameters controlling rank). g(y,z) is an independent instance. -- f and g are encoded as 2D quantics MPOs on a box [-L, L]^2 with R bits per axis. -- Task: MPO-MPO contraction h(x,z) = sum_y f(x,y) g(y,z) * Delta_y, i.e. the - discretized integral over the shared variable. -- Exact reference: for L large and R large, h converges to the closed-form Gaussian - integral int f(x,y) g(y,z) dy (Gaussian x Gaussian in y integrates analytically). - Error is measured against this closed form on sample points; box truncation and - discretization error are controlled by L and R and reported alongside. - -Sweep: R (bits per axis), number of Gaussians / width range. - -Algorithms: naive contraction + SVD, zipup, fitting (TT/MPO forms in -tensor4all-simplett / itensorlike). A TreeTN run of the same problem is a stretch -goal, not required for the initial version. - -Measured: wall time, max relative error vs analytic result, output bond dimension. - -## Correctness reference (Julia) - -Inputs that must be generated on the fly are generated in Rust only; there is no -duplicate instance construction on the Julia side. The Rust runner writes the input -TT/MPO objects (and the computed results where useful) in ITensor-compatible HDF5 -format via tensor4all-hdf5. `julia/` contains a small script (ITensors / Quantics.jl -based) that reads those HDF5 files and checks agreement within tolerance (e.g. -contracting or sampling the loaded objects against the analytic reference). This is a -test, run manually or in CI smoke, not a performance comparison. - -## Results workflow - -- `scripts/run_all.sh ` runs all cases, writes raw JSON under - `result//raw/`, then invokes the Python report generator. -- Reports: `result//elementwise_fourier.md` and - `result//mpo_mpo_quantics.md`, each with a summary table and scaling - plots (time vs chi, error vs chi) as committed SVGs. README links to the latest - reports. Historical results live in git history only. -- Initial profile: `mac-cpu` (Apple Silicon, Accelerate). Profile metadata (machine, - commit hashes of this repo and the tensor4all-rs pin, thread count) recorded in a - `run.yaml` next to the reports. -- CI (GitHub Actions): build + smoke run (smallest instance, 1 repeat) + Julia - correctness check. No performance numbers from CI are ever committed. - -## Error handling and reproducibility - -- All randomness behind explicit seeds recorded in the JSON output. -- Runner fails loudly (nonzero exit) if any algorithm's error exceeds a sanity bound - (10x the requested tolerance) so silently-wrong timings never enter reports. -- JSON schema carries a version field; report generator rejects unknown versions. - -## Testing - -Test format stays deliberately flexible: no rigid harness or fixed fixture layout is -imposed. Plain `#[test]` functions, per-case smoke binaries, and standalone Julia -scripts are all acceptable; tests may take tolerances and instance sizes from -environment variables or arguments so the same test scales from CI smoke to local -deep checks. - -- Unit tests for problem generators (Fourier coefficients normalization, Gaussian - analytic integral against numerical quadrature at small R). -- One end-to-end smoke test per case (tiny instance, all algorithms, error within - tolerance). -- Julia cross-check via ITensor-compatible HDF5 as above. - -## Implementation order - -1. Repo scaffold, workspace, shared harness + JSON schema, report generator skeleton. -2. Case 1 end to end (generator, 4 algorithms, report, smoke test, Julia check). -3. Case 2 end to end. -4. README with first committed mac-cpu results. diff --git a/docs/superpowers/specs/2026-08-07-latest-rev-expanded-sweep-design.md b/docs/superpowers/specs/2026-08-07-latest-rev-expanded-sweep-design.md deleted file mode 100644 index 673cbfe..0000000 --- a/docs/superpowers/specs/2026-08-07-latest-rev-expanded-sweep-design.md +++ /dev/null @@ -1,94 +0,0 @@ -# Update to latest tensor4all-rs and expand the default sweeps - -Date: 2026-08-07 -Status: implemented - -## Goal - -Benchmark the current tip of tensor4all-rs with heavier sweeps than the two and a half -minute defaults, and produce a question list for Hiroshi about the next benchmark case. - -## Decisions - -1. **Pin moves to the latest origin/main of tensor4all-rs** (`ae655a9` at design time, - re-check at execution). The single new commit over the old pin is #575, a treetci - convergence fix authored by the repo user, expected to affect input TCI construction - time in cases 2 and 3, not the measured arm errors. If arm errors move, that is a - finding to record, not to paper over. -2. **The pin update and the sweep expansion land together in one commit**, by explicit - instruction of the repo user, overriding the AGENTS.md rule that a bump gets its own - commit. Old results are superseded, not preserved for comparison. -3. **Default sweeps grow to a roughly 20 minute full run.** Amended later the same day - after user feedback: instead of regenerating `result/mac-cpu` in place, profiles are - split per physical machine. `mac-cpu` stays frozen as the maintainer's machine's - record at the previous pin, and this sweep lands in `mac-m1-8gb`. `run.yaml` gains - chip and memory fields and drops the hostname for privacy. -4. **No new benchmark case yet.** Candidate directions and open questions go to Hiroshi - first (see below). - -## Plan of work - -1. Update every `rev` in `Cargo.toml` to the latest tensor4all-rs origin/main. All seven - crates move together. -2. Probe actual costs on the new rev with `OUT_DIR` pointed at a scratch directory: - cases 2 and 3 at R = 12 and 14, case 1 at K = 128. The old R = 12 naive figure - (12.6 s) predates #575 and may be stale. -3. Fix the new defaults from the probe, targeting about 20 minutes for - `scripts/run_all.sh mac-cpu`. Working hypothesis: `BENCH_RS` default `6,8,10,12,14` - for cases 2 and 3, `BENCH_KS` default extended to 128 for case 1. If R = 14 naive - blows the budget, stop the default at 12 and note the cost of 14 in the README. - Keep every default arm enabled: comparability at equal budget is the point of the - suite, so shrinking `BENCH_ALGOS` is not on the table for defaults. -4. Run `scripts/run_all.sh mac-cpu` from a clean tree. All sanity gates must pass. -5. Update the README: pinned rev references, the quoted error and timing numbers in the - case 2 and 3 descriptions and the cost notes, the environment knob defaults table, - and the known issue 6 wording that names the pinned rev. -6. Commit everything as one commit: Cargo.toml, Cargo.lock, runner defaults, README, - `result/mac-cpu`. - -## Expectations to verify, not assume - -- Case 2 and 3 arm errors should be unchanged by #575. Compare against the superseded - numbers before discarding them. -- Case 2 error curves sit on the 1e-8 reference floor from R = 6 (known issue 4), so - the expanded R range adds timing information, not accuracy information. That is - expected and already documented. -- Input chi saturates around 70 to 80 for the default mixtures, so `BENCH_MAX_BOND` - (512) should stay slack at R = 14. If chi_in drifts up instead, the fixed output - budget `chi_in` changes meaning across R and the report note should say so. - -## Next case and direction, asked and answered - -Candidate directions for a fourth case: - -- (a) Benchmark TCI or quantics construction itself. All current cases exclude input - construction from the timed region, but construction performance is live upstream - work (#575 is a construction fix). -- (b) Tree topologies. treetn supports non-chain topologies, every current case is a - chain. A tree contraction case would exercise what treetn uniquely offers. -- (c) Cross-language timing against the Julia tensor4all stack on identical instances. - Half the infrastructure exists (HDF5 export, Julia readback), but a timing harness - with proper warmup would be new work (AGENTS.md warns about JIT). -- (d) Higher dimension: 3D quantics, fused site dimension 8. - -Answers, from the maintainer's review of the pull request on 2026-08-07: - -1. Fourth case: benchmark TCI or quantics construction first, option (a), since #575 - changes that path directly and every current case excludes construction from the - timed region. -2. simplett `contract_fit`: tensor4all-rs#571 is still open with no assignee or - milestone, so keep the simplett fit arm excluded. -3. simplett elementwise product for tensor trains: no public issue or plan exists. - Track it separately only when it blocks planned work. -4. Keep `mac-m1-8gb` as a machine-specific profile, but do not use its memory-bound - naive timings as the cross-machine headline. -5. `threads: default` is acceptable for this profile. Pin a numeric thread count for a - future official cross-machine sweep. -6. Keep `BENCH_BOX_L` at 6. If higher accuracy comparisons are needed, use a - finite-box analytic reference rather than only enlarging the box at fixed R. -7. Per-machine profiles, the chip and memory fields, and the hostname removal are - accepted as implemented here. - -The branch, pull request and human merge policy proposed alongside this work was -removed from the change: it belongs in a separate change, made as accepted maintainer -policy rather than as a proposal awaiting veto. diff --git a/julia/Project.toml b/julia/Project.toml deleted file mode 100644 index 37fa888..0000000 --- a/julia/Project.toml +++ /dev/null @@ -1,11 +0,0 @@ -[deps] -HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" -ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5" -ITensorMPS = "0d1a4710-d33b-49a5-8f18-73bdf49b47e2" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" - -[compat] -HDF5 = "0.17" -ITensorMPS = "0.4" -ITensors = "0.9" -JSON3 = "1" diff --git a/julia/check_elementwise.jl b/julia/check_elementwise.jl deleted file mode 100644 index 7d69354..0000000 --- a/julia/check_elementwise.jl +++ /dev/null @@ -1,47 +0,0 @@ -# Usage: julia --project=julia julia/check_elementwise.jl -# Reads instance-k.h5 (MPS groups "f","g") and instance-k.json, -# evaluates both MPS at sample grid points, compares to the analytic series. -using HDF5, ITensors, ITensorMPS, JSON3 -using Random -Random.seed!(0) - -dir, k = ARGS[1], ARGS[2] -meta = JSON3.read(read(joinpath(dir, "instance-k$k.json"), String)) -R = meta.r -@assert meta.k_max == parse(Int, k) -# Truncation is norm-relative, so the pointwise error scales with the exported -# tolerance rather than being bounded by a fixed absolute number. -threshold = 1e3 * meta.tolerance - -coeffs(v) = [complex(c[1], c[2]) for c in v] -series(c, x) = sum(c[j+1] * exp(2im * pi * j * x) for j in 0:length(c)-1) - -function eval_mps(psi::MPS, bits::Vector{Int}) - s = siteinds(psi) - v = ITensor(1.0) - for n in eachindex(psi) - v *= psi[n] * onehot(s[n] => bits[n] + 1) - end - return scalar(v) -end - -fails = 0 -h5open(joinpath(dir, "instance-k$k.h5"), "r") do file - for (name, cs) in (("f", coeffs(meta.f_coeffs)), ("g", coeffs(meta.g_coeffs))) - psi = read(file, name, MPS) - @assert length(psi) == R - for trial in 1:50 - i = rand(0:(2^R - 1)) - bits = [Int((i >> (R - n)) & 1) for n in 1:R] # MSB first - x = i / 2^R - got = eval_mps(psi, bits) - want = series(cs, x) - if abs(got - want) > threshold - global fails += 1 - println("MISMATCH $name x=$x got=$got want=$want") - end - end - end -end -fails == 0 || error("$fails mismatches") -println("check_elementwise: OK") diff --git a/julia/check_elementwise_gauss2d.jl b/julia/check_elementwise_gauss2d.jl deleted file mode 100644 index 8872b29..0000000 --- a/julia/check_elementwise_gauss2d.jl +++ /dev/null @@ -1,71 +0,0 @@ -# Usage: julia --project=julia julia/check_elementwise_gauss2d.jl -# Reads instance-r.h5 (MPS groups "f","g", site dim 4 = fused (x,y) bit pair) -# and instance-r.json, evaluates both MPS at random fused grid indices and -# compares to the analytic Gaussian-mixture formula. -# This is the case-3 mirror of check_mpo_mpo.jl. The two are near identical -# because the two cases export the same kind of instance, a pair of fused -# site-dim-4 quantics TTs of Gaussian mixtures; only the case name differs, and -# the copy is kept so each case's check can be read and run on its own. -using HDF5, ITensors, ITensorMPS, JSON3 -using Random -Random.seed!(0) - -dir, rstr = ARGS[1], ARGS[2] -R = parse(Int, rstr) -meta = JSON3.read(read(joinpath(dir, "instance-r$rstr.json"), String)) -@assert meta.r == R -@assert meta.case == "elementwise_gauss2d" -L = meta.box_l -# The exported TTs are TCI approximations at meta.tolerance, and the truncation -# is norm-relative, so the pointwise error scales with the tolerance rather than -# being bounded by a fixed absolute number (same reasoning as check_elementwise). -threshold = 1e3 * meta.tolerance - -function mixture(m, x, y) - s = 0.0 - for i in eachindex(m.weights) - cx, cy = m.centers[i] - s += m.weights[i] * exp(-m.alphas[i] * ((x - cx)^2 + (y - cy)^2)) - end - return s -end - -coord(i) = -L + i * 2L / 2^R - -function eval_mps(psi::MPS, locals::Vector{Int}) - s = siteinds(psi) - v = ITensor(1.0) - for n in eachindex(psi) - v *= psi[n] * onehot(s[n] => locals[n] + 1) - end - return scalar(v) -end - -fails = 0 -maxdev = 0.0 -h5open(joinpath(dir, "instance-r$rstr.h5"), "r") do file - for (name, m) in (("f", meta.f), ("g", meta.g)) - psi = read(file, name, MPS) - @assert length(psi) == R - @assert all(dim(s) == 4 for s in siteinds(psi)) - for trial in 1:50 - ix, iy = rand(0:(2^R - 1)), rand(0:(2^R - 1)) - xb = [Int((ix >> (R - n)) & 1) for n in 1:R] # MSB first - yb = [Int((iy >> (R - n)) & 1) for n in 1:R] - # Fused local index s = s1 + 2*s2, x (variable 1) least significant; - # matches the Rust side (see gaussian::to_quantics_fused_tt). - fused = [xb[n] + 2 * yb[n] for n in 1:R] - got = eval_mps(psi, fused) - want = mixture(m, coord(ix), coord(iy)) - dev = abs(got - want) / max(1.0, abs(want)) - global maxdev = max(maxdev, dev) - if dev > threshold - global fails += 1 - println("MISMATCH $name ($(coord(ix)), $(coord(iy))): $got vs $want") - end - end - end -end -println("max relative deviation: $maxdev (threshold $threshold)") -fails == 0 || error("$fails mismatches") -println("check_elementwise_gauss2d: OK") diff --git a/julia/check_mpo_mpo.jl b/julia/check_mpo_mpo.jl deleted file mode 100644 index 2ee754d..0000000 --- a/julia/check_mpo_mpo.jl +++ /dev/null @@ -1,69 +0,0 @@ -# Usage: julia --project=julia julia/check_mpo_mpo.jl -# Reads instance-r.h5 (MPS groups "f","g", site dim 4 = fused (x,y) bit pair) -# and instance-r.json, evaluates both MPS at random fused grid indices and -# compares to the analytic Gaussian-mixture formula. -using HDF5, ITensors, ITensorMPS, JSON3 -using Random -Random.seed!(0) - -dir, rstr = ARGS[1], ARGS[2] -R = parse(Int, rstr) -meta = JSON3.read(read(joinpath(dir, "instance-r$rstr.json"), String)) -@assert meta.r == R -# Cases 2 and 3 both export instance-r.{h5,json}, so a shared export -# directory would silently hand this script the other case's instance. -@assert meta.case == "mpo_mpo_quantics" -L = meta.box_l -# The exported TTs are TCI approximations at meta.tolerance, and the truncation -# is norm-relative, so the pointwise error scales with the tolerance rather than -# being bounded by a fixed absolute number (same reasoning as check_elementwise). -threshold = 1e3 * meta.tolerance - -function mixture(m, x, y) - s = 0.0 - for i in eachindex(m.weights) - cx, cy = m.centers[i] - s += m.weights[i] * exp(-m.alphas[i] * ((x - cx)^2 + (y - cy)^2)) - end - return s -end - -coord(i) = -L + i * 2L / 2^R - -function eval_mps(psi::MPS, locals::Vector{Int}) - s = siteinds(psi) - v = ITensor(1.0) - for n in eachindex(psi) - v *= psi[n] * onehot(s[n] => locals[n] + 1) - end - return scalar(v) -end - -fails = 0 -maxdev = 0.0 -h5open(joinpath(dir, "instance-r$rstr.h5"), "r") do file - for (name, m) in (("f", meta.f), ("g", meta.g)) - psi = read(file, name, MPS) - @assert length(psi) == R - @assert all(dim(s) == 4 for s in siteinds(psi)) - for trial in 1:50 - ix, iy = rand(0:(2^R - 1)), rand(0:(2^R - 1)) - xb = [Int((ix >> (R - n)) & 1) for n in 1:R] # MSB first - yb = [Int((iy >> (R - n)) & 1) for n in 1:R] - # Fused local index s = s1 + 2*s2, x (variable 1) least significant; - # matches the Rust side (see gaussian::to_quantics_mpo). - fused = [xb[n] + 2 * yb[n] for n in 1:R] - got = eval_mps(psi, fused) - want = mixture(m, coord(ix), coord(iy)) - dev = abs(got - want) / max(1.0, abs(want)) - global maxdev = max(maxdev, dev) - if dev > threshold - global fails += 1 - println("MISMATCH $name ($(coord(ix)), $(coord(iy))): $got vs $want") - end - end - end -end -println("max relative deviation: $maxdev (threshold $threshold)") -fails == 0 || error("$fails mismatches") -println("check_mpo_mpo: OK") diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 4c34227..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,5 +0,0 @@ -[project] -name = "t4a-bench-report" -version = "0.1.0" -requires-python = ">=3.11" -dependencies = ["matplotlib>=3.8", "numpy>=1.26"] diff --git a/result/linux-epyc-7713p/mpo_mpo_aniso_input_scaling.md b/result/linux-epyc-7713p/mpo_mpo_aniso_input_scaling.md deleted file mode 100644 index bea4183..0000000 --- a/result/linux-epyc-7713p/mpo_mpo_aniso_input_scaling.md +++ /dev/null @@ -1,51 +0,0 @@ -# Anisotropic Gaussian MPO input and patch scaling - -This focused case-6 input study measures adaptive patching through compressed input bond dimension `chi_in ≈ 1000`. It uses the unchanged constant-density random anisotropic family (`sigma_minor = 0.05`, log-uniform aspect ratio in `[1, 8]`, independent angle, center, and positive weight per Gaussian). - -## Construction and accuracy - -The input pipeline is: - -1. fused two-variable TCI at relative tolerance `1e-8`; -2. global relative-L2 SVD truncation at `1e-6`; -3. adaptive input truncation with per-patch cap 128. - -TCI evaluates the same random mixture through a spatial index. A component is omitted only outside a radius where its individual Gaussian is below a common exponent threshold. Since all weights are positive, the sum of all omitted tails is bounded pointwise by `1e-12`. The committed sampled input errors include this bound and remain below `1e-5` after global SVD truncation. - -The alternative multiscale constructor builds one randomly rotated Gaussian directly. It marks points every half minor-axis standard deviation along the major-axis ridge as unsafe. The focused test covers `rho = 8`, a 45-degree rotation, and `R = 10`, and requires maximum sampled absolute error below `5e-8` at polynomial degree 28. Mixtures can be formed by adding these single-Gaussian QTTs with intermediate SVD compression. This path preserves the instance family but is not used for the large sweep because its per-Gaussian construction cost scales linearly with `N`; spatially indexed TCI reaches the requested rank regime efficiently. - -## Reproducible settings - -These input-only records were collected separately from the profile's earlier contraction sweep. The settings below, including core 0, are authoritative for these records rather than the contraction affinity in `run.yaml`. - -- Machine: AMD EPYC 7713P 64-Core Processor -- CPU affinity: core 0 (`taskset -c 0`) -- `RAYON_NUM_THREADS=1`, `OPENBLAS_NUM_THREADS=1`, `OMP_NUM_THREADS=1` -- `BENCH_INPUT_GENERATOR=tci` -- `BENCH_INPUT_TCI_RTOL=1e-8` -- `BENCH_TCI_LOCAL_ABS_TOL=1e-12` -- `BENCH_TCI_INITIAL_PIVOTS=8` (deterministic center-derived pivots) -- `BENCH_INPUT_SVD_RTOL=1e-6` -- `BENCH_PATCH_MAX_BOND=128` -- `BENCH_MAX_INPUT_CHI=1400` -- `BENCH_MAX_BOND=512, 512, 1280, 3072, 3584` for `N=512, 4096, 20480, 100000, 125000` -- one deterministic seed (`BENCH_SEED=0`) -- `BENCH_ERROR_SAMPLES=256` at every size - -Input generation, global SVD truncation, sampled validation, and adaptive patch preparation are all included in `preparation time`; no contraction is run (`BENCH_INPUT_ONLY=1`). - -## Results - -Each pair is `(left, right)` for the two independently drawn mixtures. - -| N | R | raw chi | compressed chi | global parameters | patches | max patch chi | patch parameters | sampled relative error | preparation time | -|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| -| 512 | 9 | 181 | 89 | (48,060, 47,608) | (1, 1) | (84, 84) | (45,056, 45,056) | (3.36e-06, 2.56e-06) | 5.08 s | -| 4,096 | 10 | 280 | 256 | (254,476, 255,736) | (6, 6) | (124, 124) | (352,704, 352,088) | (1.78e-06, 3.38e-06) | 46.36 s | -| 20,480 | 11 | 889 | 458 | (888,076, 886,408) | (30, 30) | (121, 121) | (1,775,032, 1,772,136) | (2.75e-06, 6.95e-06) | 263.99 s | -| 100,000 | 12 | 1,074 | 900 | (3,450,320, 3,454,660) | (120, 120) | (120, 121) | (9,866,732, 9,982,956) | (3.06e-06, 3.74e-06) | 1,568.20 s | -| 125,000 | 13 | 1,342 | 900 | (4,120,944, 4,113,404) | (120, 120) | (121, 123) | (11,553,076, 11,596,696) | (5.51e-06, 9.14e-06) | 2,539.63 s | - -The compressed-rank plateau reaches `chi_in = 900`, within 10% of the requested `chi_in ≈ 1000` regime. Patch count grows stepwise from 1 to 6, 30, and 120 while every patch remains below cap 128. The `N = 125,000`, `R = 13` point increases raw rank and parameter count but remains on the same compressed-rank and patch-count plateau, so increasing `N` alone does not produce a smooth patch-count curve. - -Raw JSON records are in [`raw/`](raw/) with filenames `mpo_mpo_aniso_input-tci-n*-chi*.json`. diff --git a/result/linux-epyc-7713p/mpo_mpo_aniso_patched.md b/result/linux-epyc-7713p/mpo_mpo_aniso_patched.md deleted file mode 100644 index f2d38fb..0000000 --- a/result/linux-epyc-7713p/mpo_mpo_aniso_patched.md +++ /dev/null @@ -1,54 +0,0 @@ -# Patched MPO-MPO fit contraction - -Profile metadata: [`run.yaml`](run.yaml). Raw records: [`raw/`](raw/). - -## Conditions - -- `N = 2048`, `R = 10`, relative squared-value discarded-tail cutoff `1e-8` -- patch bond cap `128`; cap `64` is intentionally excluded -- one pinned CPU core; Rayon, OpenMP, OpenBLAS, MKL and vecLib limited to one thread -- two measured runs, no warmup -- identical cached global MPO inputs for the global and patched arms -- input generation, HDF5 loading, patch construction and output conversion excluded from contraction timing - -## Results - -The reported median is the harness's upper median for two runs. - -| Input χ | Input patches (left/right) | Global runs [s] | Global median [s] | Patched runs [s] | Patched median [s] | Global / patched | Output patches | Max output-patch χ | Patched error | -| ---: | ---: | --- | ---: | --- | ---: | ---: | ---: | ---: | ---: | -| 128 | 1 / 1 | 3.576, 3.515 | 3.576 | 3.321, 3.292 | 3.321 | 1.08× | 1 | 78 | 3.455e-4 | -| 192 | 8 / 8 | 11.791, 11.682 | 11.791 | 13.353, 13.244 | 13.353 | 0.88× | 1 | 68 | 5.547e-4 | -| 224 | 8 / 8 | 15.348, 15.468 | 15.468 | 13.074, 13.103 | 13.103 | 1.18× | 1 | 68 | 4.917e-4 | -| 256 | 8 / 8 | 19.606, 19.558 | 19.606 | 12.274, 12.096 | 12.274 | **1.60×** | 1 | 68 | 6.281e-4 | - -The meaningful crossover is between input χ `192` and `224`: patched takes -1.13× the global time at χ `192`, while global takes 1.18× the patched time at -χ `224` and 1.60× at χ `256`. The χ `128` point has one input patch per side -and therefore does not measure a partitioning advantage. - -The χ `128`, `192`, and `224` inputs hit their respective TCI construction caps; -they are cap-limited views of the same instance, while the χ `256` input was -built with cap `384` and converged below it. - -## Input MPO size - -Pure `f64` core storage, excluding index and HDF5 metadata: - -| Input χ | Left values / MiB | Right values / MiB | Pair MiB | HDF5 MiB | -| ---: | ---: | ---: | ---: | ---: | -| 128 | 166,440 / 1.270 | 167,552 / 1.278 | 2.548 | 2.930 | -| 192 | 282,964 / 2.159 | 281,472 / 2.147 | 4.306 | 4.689 | -| 224 | 314,912 / 2.403 | 314,912 / 2.403 | 4.805 | 5.187 | -| 256 | 346,176 / 2.641 | 347,976 / 2.655 | 5.296 | 5.678 | - -## Accuracy status - -All points exceed the runner's unchanged `1e-4` sanity gate under this -ITensor-style cutoff, so each process exits nonzero after writing its records. -The records are retained because the comparison and crossover are valid, but -these runs do **not** claim that the accuracy gate passed. No tolerance or gate -was relaxed. - -The recorded rerun uses the merged tensor4all-rs revision `9e9aeda`, which is -also the revision pinned by this repository. diff --git a/result/mac-cpu/raw/elementwise_fourier-aci-k128.json b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k128.json similarity index 64% rename from result/mac-cpu/raw/elementwise_fourier-aci-k128.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-aci-k128.json index 5b27f43..df501bb 100644 --- a/result/mac-cpu/raw/elementwise_fourier-aci-k128.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k128.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "aci", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "aci_absolute_residual", "k_max": 128, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.021761625, + "wall_time_median_secs": 0.089004517, "wall_times_secs": [ - 0.022042584, - 0.021835917, - 0.021761625, - 0.021604958, - 0.021568125 + 0.082387555, + 0.082447857, + 0.089004517, + 0.097635473, + 0.097660994 ], - "max_error": 3.739538966267687e-7, + "max_error": 3.2549001017850285e-9, "input_max_bond_dim": 16, "output_max_bond_dim": 32, "output_bond_dims": [ @@ -32,8 +33,8 @@ 8, 16, 32, - 30, - 24, + 31, + 22, 17, 14, 10, @@ -47,5 +48,5 @@ 3, 2 ], - "n_params": 6808 + "n_params": 6728 } \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_fourier-aci-k16.json b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k16.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-aci-k16.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-aci-k16.json index dd2fb33..8c16ac3 100644 --- a/result/mac-cpu/raw/elementwise_fourier-aci-k16.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k16.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "aci", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "aci_absolute_residual", "k_max": 16, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.015330916, + "wall_time_median_secs": 0.072607298, "wall_times_secs": [ - 0.015438333, - 0.01535575, - 0.015330916, - 0.015303417, - 0.015325584 + 0.072295276, + 0.072607298, + 0.071219726, + 0.07676734, + 0.074792857 ], - "max_error": 7.659483799883847e-8, + "max_error": 6.0889125792547555e-9, "input_max_bond_dim": 8, "output_max_bond_dim": 16, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-aci-k32.json b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k32.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-aci-k32.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-aci-k32.json index afddfe1..eed7b93 100644 --- a/result/mac-cpu/raw/elementwise_fourier-aci-k32.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k32.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "aci", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "aci_absolute_residual", "k_max": 32, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.01622625, + "wall_time_median_secs": 0.080893221, "wall_times_secs": [ - 0.0163525, - 0.016055459, - 0.015949334, - 0.01622625, - 0.016339125 + 0.080893221, + 0.084286845, + 0.081810564, + 0.076993457, + 0.077900201 ], - "max_error": 1.1645475872769372e-7, + "max_error": 4.9389485195046555e-9, "input_max_bond_dim": 11, "output_max_bond_dim": 22, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-aci-k4.json b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k4.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-aci-k4.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-aci-k4.json index c62fa57..a625f30 100644 --- a/result/mac-cpu/raw/elementwise_fourier-aci-k4.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k4.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "aci", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "aci_absolute_residual", "k_max": 4, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.01427725, + "wall_time_median_secs": 0.073346625, "wall_times_secs": [ - 0.014389458, - 0.014311458, - 0.01427075, - 0.01427725, - 0.014246167 + 0.073346625, + 0.079311323, + 0.078380249, + 0.066438092, + 0.066982761 ], - "max_error": 5.19867295877198e-8, + "max_error": 1.163185474515363e-8, "input_max_bond_dim": 5, "output_max_bond_dim": 9, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-aci-k64.json b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k64.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-aci-k64.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-aci-k64.json index 5819738..e6bedc2 100644 --- a/result/mac-cpu/raw/elementwise_fourier-aci-k64.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k64.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "aci", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "aci_absolute_residual", "k_max": 64, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.018025167, + "wall_time_median_secs": 0.080988694, "wall_times_secs": [ - 0.018050292, - 0.018025167, - 0.01797875, - 0.018171209, - 0.017998875 + 0.084685699, + 0.081043696, + 0.080988694, + 0.079715678, + 0.080700833 ], - "max_error": 2.8596031176793327e-7, + "max_error": 4.479768054162267e-9, "input_max_bond_dim": 14, "output_max_bond_dim": 29, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-aci-k8.json b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k8.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-aci-k8.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-aci-k8.json index f0ad34c..d323b9f 100644 --- a/result/mac-cpu/raw/elementwise_fourier-aci-k8.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-aci-k8.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "aci", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "aci_absolute_residual", "k_max": 8, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.016543375, + "wall_time_median_secs": 0.07703328, "wall_times_secs": [ - 0.016712875, - 0.016254209, - 0.016631709, - 0.016543375, - 0.016496792 + 0.076406567, + 0.077433924, + 0.077004138, + 0.077243807, + 0.07703328 ], - "max_error": 6.33940386456549e-8, + "max_error": 8.172564248673398e-9, "input_max_bond_dim": 8, "output_max_bond_dim": 15, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-fit-k128.json b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k128.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-fit-k128.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-fit-k128.json index bd83900..ef18426 100644 --- a/result/mac-cpu/raw/elementwise_fourier-fit-k128.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k128.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "fit", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 128, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.073325042, + "wall_time_median_secs": 0.094403695, "wall_times_secs": [ - 0.06968, - 0.08489475, - 0.07519675, - 0.073325042, - 0.072488041 + 0.093958469, + 0.094420145, + 0.094403695, + 0.092585308, + 0.102830193 ], - "max_error": 5.738211733902406e-7, + "max_error": 1.0440436562170602e-8, "input_max_bond_dim": 16, "output_max_bond_dim": 18, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-fit-k16.json b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k16.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-fit-k16.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-fit-k16.json index 321f7a1..281ca33 100644 --- a/result/mac-cpu/raw/elementwise_fourier-fit-k16.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k16.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "fit", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 16, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.025704584, + "wall_time_median_secs": 0.085959526, "wall_times_secs": [ - 0.025711167, - 0.025607583, - 0.025552833, - 0.025750292, - 0.025704584 + 0.086297258, + 0.095016598, + 0.085959526, + 0.082297772, + 0.080652072 ], - "max_error": 2.514203903434566e-7, + "max_error": 1.6203459105343757e-8, "input_max_bond_dim": 8, "output_max_bond_dim": 10, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-fit-k32.json b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k32.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-fit-k32.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-fit-k32.json index 3852408..30433dd 100644 --- a/result/mac-cpu/raw/elementwise_fourier-fit-k32.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k32.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "fit", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 32, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.032729875, + "wall_time_median_secs": 0.087356497, "wall_times_secs": [ - 0.0320385, - 0.032327584, - 0.032996709, - 0.03292775, - 0.032729875 + 0.082963386, + 0.088281891, + 0.087356497, + 0.085011142, + 0.101027997 ], - "max_error": 6.376609069615573e-7, + "max_error": 1.806461257866869e-8, "input_max_bond_dim": 11, "output_max_bond_dim": 13, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-fit-k4.json b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k4.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-fit-k4.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-fit-k4.json index 4bd6892..fcc7425 100644 --- a/result/mac-cpu/raw/elementwise_fourier-fit-k4.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k4.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "fit", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 4, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.0214, + "wall_time_median_secs": 0.078786114, "wall_times_secs": [ - 0.021431375, - 0.0214, - 0.021358375, - 0.021279375, - 0.021454833 + 0.078285316, + 0.078639868, + 0.078786114, + 0.085675956, + 0.081483132 ], - "max_error": 7.943938987978122e-8, + "max_error": 1.213100683047753e-8, "input_max_bond_dim": 5, "output_max_bond_dim": 8, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-fit-k64.json b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k64.json similarity index 69% rename from result/mac-cpu/raw/elementwise_fourier-fit-k64.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-fit-k64.json index 2fc88ef..5fc6e55 100644 --- a/result/mac-cpu/raw/elementwise_fourier-fit-k64.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k64.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "fit", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 64, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.044990584, + "wall_time_median_secs": 0.0967479, "wall_times_secs": [ - 0.045596042, - 0.044990584, - 0.044972542, - 0.044959416, - 0.04505025 + 0.102443599, + 0.0967479, + 0.097766798, + 0.086655202, + 0.086008847 ], - "max_error": 6.491125184244356e-7, + "max_error": 1.812611705675517e-8, "input_max_bond_dim": 14, "output_max_bond_dim": 16, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-fit-k8.json b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k8.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-fit-k8.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-fit-k8.json index e05fd56..9b633db 100644 --- a/result/mac-cpu/raw/elementwise_fourier-fit-k8.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-fit-k8.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "fit", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 8, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.024674292, + "wall_time_median_secs": 0.080764357, "wall_times_secs": [ - 0.024181667, - 0.024674292, - 0.025404334, - 0.025126542, - 0.024396666 + 0.080649512, + 0.088879823, + 0.088321452, + 0.080764357, + 0.079818591 ], - "max_error": 7.435456871928251e-8, + "max_error": 1.0663293842057099e-8, "input_max_bond_dim": 8, "output_max_bond_dim": 8, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-naive-k128.json b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k128.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-naive-k128.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-naive-k128.json index c73db32..2c9ed53 100644 --- a/result/mac-cpu/raw/elementwise_fourier-naive-k128.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k128.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "naive", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 128, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.00970125, + "wall_time_median_secs": 0.016860537, "wall_times_secs": [ - 0.00997625, - 0.00974925, - 0.00970125, - 0.009686584, - 0.009682292 + 0.018197296, + 0.01695544, + 0.016860537, + 0.016032997, + 0.016813885 ], - "max_error": 5.744879925550514e-7, + "max_error": 1.044136843668186e-8, "input_max_bond_dim": 16, "output_max_bond_dim": 18, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-naive-k16.json b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k16.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-naive-k16.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-naive-k16.json index 4578c9c..67ee637 100644 --- a/result/mac-cpu/raw/elementwise_fourier-naive-k16.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k16.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "naive", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 16, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.001640917, + "wall_time_median_secs": 0.003332062, "wall_times_secs": [ - 0.001648125, - 0.001629958, - 0.001640917, - 0.00164475, - 0.001619792 + 0.003310371, + 0.003332062, + 0.003437796, + 0.003610312, + 0.003244419 ], - "max_error": 2.514227072072243e-7, + "max_error": 1.6202185620932022e-8, "input_max_bond_dim": 8, "output_max_bond_dim": 10, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-naive-k32.json b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k32.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-naive-k32.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-naive-k32.json index 8bcc324..0043e8f 100644 --- a/result/mac-cpu/raw/elementwise_fourier-naive-k32.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k32.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "naive", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 32, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.00275775, + "wall_time_median_secs": 0.006155545, "wall_times_secs": [ - 0.002791, - 0.002783292, - 0.002755625, - 0.00275775, - 0.002755667 + 0.006215827, + 0.006239299, + 0.005883445, + 0.006155545, + 0.00546982 ], - "max_error": 6.377530790274987e-7, + "max_error": 1.8063460329673993e-8, "input_max_bond_dim": 11, "output_max_bond_dim": 13, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-naive-k4.json b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k4.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-naive-k4.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-naive-k4.json index 3784d79..b69ec4d 100644 --- a/result/mac-cpu/raw/elementwise_fourier-naive-k4.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k4.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "naive", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 4, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.001114291, + "wall_time_median_secs": 0.00189061, "wall_times_secs": [ - 0.0011735, - 0.001144667, - 0.001114291, - 0.001108417, - 0.001034792 + 0.001862999, + 0.0019182, + 0.00192607, + 0.001889009, + 0.00189061 ], - "max_error": 7.932838114995547e-8, + "max_error": 1.2110321323993066e-8, "input_max_bond_dim": 5, "output_max_bond_dim": 8, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-naive-k64.json b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k64.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-naive-k64.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-naive-k64.json index 233c9ac..3db72b5 100644 --- a/result/mac-cpu/raw/elementwise_fourier-naive-k64.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k64.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "naive", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 64, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.005005084, + "wall_time_median_secs": 0.009582771, "wall_times_secs": [ - 0.005029583, - 0.005006417, - 0.005005084, - 0.004982125, - 0.005001375 + 0.009143684, + 0.009114804, + 0.009582771, + 0.010531065, + 0.009680645 ], - "max_error": 6.489718769771527e-7, + "max_error": 1.8125685022055363e-8, "input_max_bond_dim": 14, "output_max_bond_dim": 16, "output_bond_dims": [ diff --git a/result/mac-cpu/raw/elementwise_fourier-naive-k8.json b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k8.json similarity index 68% rename from result/mac-cpu/raw/elementwise_fourier-naive-k8.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-naive-k8.json index eae9c7b..cbec357 100644 --- a/result/mac-cpu/raw/elementwise_fourier-naive-k8.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-naive-k8.json @@ -3,9 +3,10 @@ "case": "elementwise_fourier", "algorithm": "naive", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 8, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.001214291, + "wall_time_median_secs": 0.002576274, "wall_times_secs": [ - 0.001214291, - 0.001197625, - 0.00120875, - 0.001231042, - 0.001232916 + 0.002674438, + 0.002536663, + 0.002576274, + 0.002872715, + 0.002540953 ], - "max_error": 7.423232997232557e-8, + "max_error": 1.0657101011854099e-8, "input_max_bond_dim": 8, "output_max_bond_dim": 8, "output_bond_dims": [ diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k128.json b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k128.json similarity index 63% rename from result/mac-m1-8gb/raw/elementwise_fourier-fit-k128.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k128.json index cfa11f2..c7416a5 100644 --- a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k128.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k128.json @@ -1,11 +1,12 @@ { "schema_version": 1, "case": "elementwise_fourier", - "algorithm": "fit", + "algorithm": "zipup", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 128, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.079603, + "wall_time_median_secs": 0.044607123, "wall_times_secs": [ - 0.079603, - 0.0796725, - 0.077073834, - 0.080484291, - 0.079400834 + 0.043259853, + 0.043811333, + 0.044607123, + 0.044970135, + 0.0447985 ], - "max_error": 5.738211931651007e-7, + "max_error": 1.0638873829596218e-8, "input_max_bond_dim": 16, "output_max_bond_dim": 18, "output_bond_dims": [ @@ -46,5 +47,6 @@ 3, 3, 2 - ] + ], + "n_params": 2258 } \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k16.json b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k16.json similarity index 62% rename from result/mac-m1-8gb/raw/elementwise_fourier-fit-k16.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k16.json index 2c7acf2..d149204 100644 --- a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k16.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k16.json @@ -1,11 +1,12 @@ { "schema_version": 1, "case": "elementwise_fourier", - "algorithm": "fit", + "algorithm": "zipup", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 16, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.0305235, + "wall_time_median_secs": 0.038437857, "wall_times_secs": [ - 0.029720209, - 0.029351625, - 0.0305235, - 0.033423333, - 0.033965042 + 0.037336217, + 0.038437857, + 0.037632007, + 0.038547541, + 0.044734217 ], - "max_error": 2.514203787545623e-7, + "max_error": 1.6363347356180935e-8, "input_max_bond_dim": 8, "output_max_bond_dim": 10, "output_bond_dims": [ @@ -46,5 +47,6 @@ 2, 2, 2 - ] + ], + "n_params": 900 } \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k32.json b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k32.json similarity index 62% rename from result/mac-m1-8gb/raw/elementwise_fourier-fit-k32.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k32.json index c2ba2ca..e9dacbc 100644 --- a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k32.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k32.json @@ -1,11 +1,12 @@ { "schema_version": 1, "case": "elementwise_fourier", - "algorithm": "fit", + "algorithm": "zipup", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 32, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.038845791, + "wall_time_median_secs": 0.038147366, "wall_times_secs": [ - 0.038091875, - 0.036870708, - 0.039785666, - 0.042719583, - 0.038845791 + 0.038861182, + 0.038147366, + 0.037622807, + 0.039008418, + 0.03770783 ], - "max_error": 6.376609129164904e-7, + "max_error": 2.00075633197621e-8, "input_max_bond_dim": 11, "output_max_bond_dim": 13, "output_bond_dims": [ @@ -36,7 +37,7 @@ 7, 6, 5, - 5, + 4, 4, 4, 3, @@ -46,5 +47,6 @@ 2, 2, 2 - ] + ], + "n_params": 1182 } \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k4.json b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k4.json similarity index 62% rename from result/mac-m1-8gb/raw/elementwise_fourier-fit-k4.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k4.json index e8b6bf2..63353ad 100644 --- a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k4.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k4.json @@ -1,11 +1,12 @@ { "schema_version": 1, "case": "elementwise_fourier", - "algorithm": "fit", + "algorithm": "zipup", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 4, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.022955916, + "wall_time_median_secs": 0.036320029, "wall_times_secs": [ - 0.022955916, - 0.022937417, - 0.022870125, - 0.0907145, - 0.034338125 + 0.037146849, + 0.036984494, + 0.036073801, + 0.036309169, + 0.036320029 ], - "max_error": 7.943939048205503e-8, + "max_error": 1.1974477221977903e-8, "input_max_bond_dim": 5, "output_max_bond_dim": 8, "output_bond_dims": [ @@ -46,5 +47,6 @@ 2, 2, 2 - ] + ], + "n_params": 606 } \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k64.json b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k64.json similarity index 62% rename from result/mac-m1-8gb/raw/elementwise_fourier-naive-k64.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k64.json index 94d8ca8..035a8e1 100644 --- a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k64.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k64.json @@ -1,11 +1,12 @@ { "schema_version": 1, "case": "elementwise_fourier", - "algorithm": "naive", + "algorithm": "zipup", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 64, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.006503083, + "wall_time_median_secs": 0.044972836, "wall_times_secs": [ - 0.006648333, - 0.006275917, - 0.006503083, - 0.006191083, - 0.006558209 + 0.045332789, + 0.044972836, + 0.045107411, + 0.042652411, + 0.043084187 ], - "max_error": 6.489719276280827e-7, + "max_error": 1.855719929232943e-8, "input_max_bond_dim": 14, "output_max_bond_dim": 16, "output_bond_dims": [ @@ -46,5 +47,6 @@ 3, 2, 2 - ] + ], + "n_params": 1638 } \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k8.json b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k8.json similarity index 62% rename from result/mac-m1-8gb/raw/elementwise_fourier-fit-k8.json rename to result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k8.json index ad72032..4b797e6 100644 --- a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k8.json +++ b/result/linux-epyc-7713p/raw/elementwise_fourier-zipup-k8.json @@ -1,11 +1,12 @@ { "schema_version": 1, "case": "elementwise_fourier", - "algorithm": "fit", + "algorithm": "zipup", "params": { - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", "error_seed": 999, "fit_nfullsweeps": 2, + "internal_tolerance_metric": "relative_l2_svd", "k_max": 8, "max_bond": 4096, "n_error_samples": 256, @@ -15,15 +16,15 @@ }, "seed": 0, "tolerance": 1e-8, - "wall_time_median_secs": 0.027111334, + "wall_time_median_secs": 0.037141299, "wall_times_secs": [ - 0.026187084, - 0.027079833, - 0.028503917, - 0.027111334, - 0.02752025 + 0.037609727, + 0.03714979, + 0.037141299, + 0.036078701, + 0.03635448 ], - "max_error": 7.435455260018412e-8, + "max_error": 1.0797260941143738e-8, "input_max_bond_dim": 8, "output_max_bond_dim": 8, "output_bond_dims": [ @@ -46,5 +47,6 @@ 2, 2, 2 - ] + ], + "n_params": 726 } \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi16.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi16.json new file mode 100644 index 0000000..7facede --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi16.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.10606601717798216, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n2-r6-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 3.938045631, + "input_compression_secs": 0.001676991, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 16, + "input_params": 3740, + "input_patch_count": 2, + "input_patch_params": 3740, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_scale_relative_residual", + "interpolation_tolerance": 1e-10, + "left_chi": 16, + "left_input_sampled_relative_l2": 1.2777851917357638e-6, + "n_gauss": 2, + "patch_build_secs": 0.023821852, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 6, + "raw_left_chi": 32, + "raw_left_params": 4640, + "raw_right_chi": 26, + "raw_right_params": 3872, + "rho_max": 8.0, + "right_chi": 16, + "right_input_sampled_relative_l2": 9.42870060096915e-7, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 0.008655487, + "wall_times_secs": [ + 0.008655487 + ], + "max_error": 1.3982004615948938e-6, + "input_max_bond_dim": 16, + "output_max_bond_dim": 47, + "output_bond_dims": [ + 4, + 16, + 47, + 16, + 4 + ], + "n_params": 6560, + "input_build_secs": 3.938045631 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi24.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi24.json new file mode 100644 index 0000000..5af612d --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi24.json @@ -0,0 +1,59 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.2121320343559643, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n8-r7-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 27.955239246, + "input_compression_secs": 0.003891542, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 24, + "input_params": 7924, + "input_patch_count": 2, + "input_patch_params": 7924, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_scale_relative_residual", + "interpolation_tolerance": 1e-10, + "left_chi": 23, + "left_input_sampled_relative_l2": 1.7758182520386608e-6, + "n_gauss": 8, + "patch_build_secs": 0.038276128, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 7, + "raw_left_chi": 50, + "raw_left_params": 12720, + "raw_right_chi": 50, + "raw_right_params": 12720, + "rho_max": 8.0, + "right_chi": 24, + "right_input_sampled_relative_l2": 1.4847849136070642e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 0.019403469, + "wall_times_secs": [ + 0.019403469 + ], + "max_error": 2.941789640271412e-6, + "input_max_bond_dim": 24, + "output_max_bond_dim": 64, + "output_bond_dims": [ + 4, + 16, + 64, + 59, + 15, + 4 + ], + "n_params": 23268, + "input_build_secs": 27.955239246 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi41.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi41.json new file mode 100644 index 0000000..4bf5b3c --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi41.json @@ -0,0 +1,60 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.4242640687119286, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n32-r8-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 167.590778715, + "input_compression_secs": 0.009321469, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 41, + "input_params": 18380, + "input_patch_count": 2, + "input_patch_params": 18380, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_scale_relative_residual", + "interpolation_tolerance": 1e-10, + "left_chi": 41, + "left_input_sampled_relative_l2": 1.8640164827991147e-6, + "n_gauss": 32, + "patch_build_secs": 0.103943465, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 8, + "raw_left_chi": 64, + "raw_left_params": 27592, + "raw_right_chi": 64, + "raw_right_params": 27592, + "rho_max": 8.0, + "right_chi": 40, + "right_input_sampled_relative_l2": 2.2322759981295966e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 0.065373981, + "wall_times_secs": [ + 0.065373981 + ], + "max_error": 3.4680687275895684e-6, + "input_max_bond_dim": 41, + "output_max_bond_dim": 183, + "output_bond_dims": [ + 4, + 16, + 64, + 183, + 60, + 15, + 4 + ], + "n_params": 98992, + "input_build_secs": 167.590778715 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi64.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi64.json new file mode 100644 index 0000000..d7ea309 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_aci-chi64.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.8485281374238572, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n128-r9-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 927.013950836, + "input_compression_secs": 0.017406887, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 64, + "input_params": 43200, + "input_patch_count": 2, + "input_patch_params": 43200, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_scale_relative_residual", + "interpolation_tolerance": 1e-10, + "left_chi": 64, + "left_input_sampled_relative_l2": 2.168208907580374e-6, + "n_gauss": 128, + "patch_build_secs": 0.786904454, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 9, + "raw_left_chi": 99, + "raw_left_params": 62240, + "raw_right_chi": 98, + "raw_right_params": 60416, + "rho_max": 8.0, + "right_chi": 64, + "right_input_sampled_relative_l2": 2.8526224091517408e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 0.21269032, + "wall_times_secs": [ + 0.21269032 + ], + "max_error": 2.7045742110158743e-6, + "input_max_bond_dim": 64, + "output_max_bond_dim": 256, + "output_bond_dims": [ + 4, + 16, + 64, + 256, + 193, + 60, + 15, + 4 + ], + "n_params": 317712, + "input_build_secs": 927.013950836 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi16.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi16.json new file mode 100644 index 0000000..1f43f0b --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi16.json @@ -0,0 +1,59 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.10606601717798216, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n2-r6-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 3.938045631, + "input_compression_secs": 0.001676991, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 16, + "input_params": 3740, + "input_patch_count": 2, + "input_patch_params": 3740, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 16, + "left_input_sampled_relative_l2": 1.2777851917357638e-6, + "n_gauss": 2, + "patch_build_secs": 0.023821852, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 6, + "raw_left_chi": 32, + "raw_left_params": 4640, + "raw_right_chi": 26, + "raw_right_params": 3872, + "rho_max": 8.0, + "right_chi": 16, + "right_input_sampled_relative_l2": 9.42870060096915e-7, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.028473381, + "wall_times_secs": [ + 0.028473381 + ], + "max_error": 2.293034801942847e-6, + "input_max_bond_dim": 16, + "output_max_bond_dim": 17, + "output_bond_dims": [ + 4, + 16, + 17, + 11, + 4 + ], + "n_params": 2300, + "rtol": 1e-6, + "input_build_secs": 3.938045631 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi24.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi24.json new file mode 100644 index 0000000..5775f0a --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi24.json @@ -0,0 +1,60 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.2121320343559643, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n8-r7-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 27.955239246, + "input_compression_secs": 0.003891542, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 24, + "input_params": 7924, + "input_patch_count": 2, + "input_patch_params": 7924, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 23, + "left_input_sampled_relative_l2": 1.7758182520386608e-6, + "n_gauss": 8, + "patch_build_secs": 0.038276128, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 7, + "raw_left_chi": 50, + "raw_left_params": 12720, + "raw_right_chi": 50, + "raw_right_params": 12720, + "rho_max": 8.0, + "right_chi": 24, + "right_input_sampled_relative_l2": 1.4847849136070642e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.042135669, + "wall_times_secs": [ + 0.042135669 + ], + "max_error": 3.4615297867646214e-6, + "input_max_bond_dim": 24, + "output_max_bond_dim": 27, + "output_bond_dims": [ + 4, + 16, + 27, + 17, + 11, + 4 + ], + "n_params": 4776, + "rtol": 1e-6, + "input_build_secs": 27.955239246 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi41.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi41.json new file mode 100644 index 0000000..8381358 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi41.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.4242640687119286, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n32-r8-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 167.590778715, + "input_compression_secs": 0.009321469, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 41, + "input_params": 18380, + "input_patch_count": 2, + "input_patch_params": 18380, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 41, + "left_input_sampled_relative_l2": 1.8640164827991147e-6, + "n_gauss": 32, + "patch_build_secs": 0.103943465, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 8, + "raw_left_chi": 64, + "raw_left_params": 27592, + "raw_right_chi": 64, + "raw_right_params": 27592, + "rho_max": 8.0, + "right_chi": 40, + "right_input_sampled_relative_l2": 2.2322759981295966e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.088815554, + "wall_times_secs": [ + 0.088815554 + ], + "max_error": 4.661153416145784e-6, + "input_max_bond_dim": 41, + "output_max_bond_dim": 48, + "output_bond_dims": [ + 4, + 16, + 48, + 27, + 16, + 10, + 4 + ], + "n_params": 11072, + "rtol": 1e-6, + "input_build_secs": 167.590778715 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi64.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi64.json new file mode 100644 index 0000000..5300eb1 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-global_fit-chi64.json @@ -0,0 +1,62 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.8485281374238572, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n128-r9-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 927.013950836, + "input_compression_secs": 0.017406887, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 64, + "input_params": 43200, + "input_patch_count": 2, + "input_patch_params": 43200, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 64, + "left_input_sampled_relative_l2": 2.168208907580374e-6, + "n_gauss": 128, + "patch_build_secs": 0.786904454, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 9, + "raw_left_chi": 99, + "raw_left_params": 62240, + "raw_right_chi": 98, + "raw_right_params": 60416, + "rho_max": 8.0, + "right_chi": 64, + "right_input_sampled_relative_l2": 2.8526224091517408e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.32920928, + "wall_times_secs": [ + 0.32920928 + ], + "max_error": 3.9932688120904025e-6, + "input_max_bond_dim": 64, + "output_max_bond_dim": 64, + "output_bond_dims": [ + 4, + 16, + 64, + 51, + 27, + 16, + 10, + 4 + ], + "n_params": 25476, + "rtol": 1e-6, + "input_build_secs": 927.013950836 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi16.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi16.json new file mode 100644 index 0000000..f3820bc --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi16.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.10606601717798216, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n2-r6-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 3.938045631, + "input_compression_secs": 0.001676991, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 16, + "input_params": 3740, + "input_patch_count": 2, + "input_patch_params": 3740, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_absolute_patch_residual_then_global_l2", + "interpolation_tolerance": 1e-10, + "left_chi": 16, + "left_input_sampled_relative_l2": 1.2777851917357638e-6, + "n_gauss": 2, + "patch_build_secs": 0.023821852, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 6, + "raw_left_chi": 32, + "raw_left_params": 4640, + "raw_right_chi": 26, + "raw_right_params": 3872, + "rho_max": 8.0, + "right_chi": 16, + "right_input_sampled_relative_l2": 9.42870060096915e-7, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.3962358748485129 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 0.021844279, + "wall_times_secs": [ + 0.021844279 + ], + "max_error": 2.2917499169125474e-6, + "input_max_bond_dim": 16, + "output_max_bond_dim": 17, + "output_bond_dims": [ + 17 + ], + "n_params": 2300, + "n_patches": 1, + "max_patch_bond": 17, + "rtol": 1e-6, + "input_build_secs": 3.938045631 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi24.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi24.json new file mode 100644 index 0000000..63b537f --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi24.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.2121320343559643, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n8-r7-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 27.955239246, + "input_compression_secs": 0.003891542, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 24, + "input_params": 7924, + "input_patch_count": 2, + "input_patch_params": 7924, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_absolute_patch_residual_then_global_l2", + "interpolation_tolerance": 1e-10, + "left_chi": 23, + "left_input_sampled_relative_l2": 1.7758182520386608e-6, + "n_gauss": 8, + "patch_build_secs": 0.038276128, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 7, + "raw_left_chi": 50, + "raw_left_params": 12720, + "raw_right_chi": 50, + "raw_right_params": 12720, + "rho_max": 8.0, + "right_chi": 24, + "right_input_sampled_relative_l2": 1.4847849136070642e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.07179505454257196 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 0.270261916, + "wall_times_secs": [ + 0.270261916 + ], + "max_error": 3.4589835341734724e-6, + "input_max_bond_dim": 24, + "output_max_bond_dim": 28, + "output_bond_dims": [ + 28 + ], + "n_params": 4908, + "n_patches": 1, + "max_patch_bond": 28, + "rtol": 1e-6, + "input_build_secs": 27.955239246 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi41.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi41.json new file mode 100644 index 0000000..3cac674 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi41.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.4242640687119286, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n32-r8-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 167.590778715, + "input_compression_secs": 0.009321469, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 41, + "input_params": 18380, + "input_patch_count": 2, + "input_patch_params": 18380, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_absolute_patch_residual_then_global_l2", + "interpolation_tolerance": 1e-10, + "left_chi": 41, + "left_input_sampled_relative_l2": 1.8640164827991147e-6, + "n_gauss": 32, + "patch_build_secs": 0.103943465, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 8, + "raw_left_chi": 64, + "raw_left_params": 27592, + "raw_right_chi": 64, + "raw_right_params": 27592, + "rho_max": 8.0, + "right_chi": 40, + "right_input_sampled_relative_l2": 2.2322759981295966e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.02689915682615195 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 2.430335695, + "wall_times_secs": [ + 2.430335695 + ], + "max_error": 4.365879400759556e-6, + "input_max_bond_dim": 41, + "output_max_bond_dim": 48, + "output_bond_dims": [ + 48 + ], + "n_params": 11740, + "n_patches": 1, + "max_patch_bond": 48, + "rtol": 1e-6, + "input_build_secs": 167.590778715 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi64.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi64.json new file mode 100644 index 0000000..89eb998 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_aci-chi64.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_aci", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.8485281374238572, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n128-r9-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 927.013950836, + "input_compression_secs": 0.017406887, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 64, + "input_params": 43200, + "input_patch_count": 2, + "input_patch_params": 43200, + "internal_tolerance": 1e-8, + "internal_tolerance_metric": "aci_absolute_patch_residual_then_global_l2", + "interpolation_tolerance": 1e-10, + "left_chi": 64, + "left_input_sampled_relative_l2": 2.168208907580374e-6, + "n_gauss": 128, + "patch_build_secs": 0.786904454, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 9, + "raw_left_chi": 99, + "raw_left_params": 62240, + "raw_right_chi": 98, + "raw_right_params": 60416, + "rho_max": 8.0, + "right_chi": 64, + "right_input_sampled_relative_l2": 2.8526224091517408e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.02378468451042246 + }, + "seed": 0, + "tolerance": 1e-8, + "wall_time_median_secs": 8.942322523, + "wall_times_secs": [ + 8.942322523 + ], + "max_error": 3.1678797598651977e-6, + "input_max_bond_dim": 64, + "output_max_bond_dim": 64, + "output_bond_dims": [ + 64 + ], + "n_params": 28028, + "n_patches": 1, + "max_patch_bond": 64, + "rtol": 1e-6, + "input_build_secs": 927.013950836 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi16.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi16.json new file mode 100644 index 0000000..a60921b --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi16.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.10606601717798216, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n2-r6-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 3.938045631, + "input_compression_secs": 0.001676991, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 16, + "input_params": 3740, + "input_patch_count": 2, + "input_patch_params": 3740, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 16, + "left_input_sampled_relative_l2": 1.2777851917357638e-6, + "n_gauss": 2, + "patch_build_secs": 0.023821852, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 6, + "raw_left_chi": 32, + "raw_left_params": 4640, + "raw_right_chi": 26, + "raw_right_params": 3872, + "rho_max": 8.0, + "right_chi": 16, + "right_input_sampled_relative_l2": 9.42870060096915e-7, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.6346639715114071 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.044863711, + "wall_times_secs": [ + 0.044863711 + ], + "max_error": 2.2917390968800337e-6, + "input_max_bond_dim": 16, + "output_max_bond_dim": 17, + "output_bond_dims": [ + 17 + ], + "n_params": 2300, + "n_patches": 1, + "max_patch_bond": 17, + "rtol": 1e-6, + "input_build_secs": 3.938045631 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi24.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi24.json new file mode 100644 index 0000000..4a813b1 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi24.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.2121320343559643, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n8-r7-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 27.955239246, + "input_compression_secs": 0.003891542, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 24, + "input_params": 7924, + "input_patch_count": 2, + "input_patch_params": 7924, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 23, + "left_input_sampled_relative_l2": 1.7758182520386608e-6, + "n_gauss": 8, + "patch_build_secs": 0.038276128, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 7, + "raw_left_chi": 50, + "raw_left_params": 12720, + "raw_right_chi": 50, + "raw_right_params": 12720, + "rho_max": 8.0, + "right_chi": 24, + "right_input_sampled_relative_l2": 1.4847849136070642e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.37364164000279826 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.112770271, + "wall_times_secs": [ + 0.112770271 + ], + "max_error": 3.4589716743211756e-6, + "input_max_bond_dim": 24, + "output_max_bond_dim": 28, + "output_bond_dims": [ + 28 + ], + "n_params": 4908, + "n_patches": 1, + "max_patch_bond": 28, + "rtol": 1e-6, + "input_build_secs": 27.955239246 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi41.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi41.json new file mode 100644 index 0000000..940e4a0 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi41.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.4242640687119286, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n32-r8-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 167.590778715, + "input_compression_secs": 0.009321469, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 41, + "input_params": 18380, + "input_patch_count": 2, + "input_patch_params": 18380, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 41, + "left_input_sampled_relative_l2": 1.8640164827991147e-6, + "n_gauss": 32, + "patch_build_secs": 0.103943465, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 8, + "raw_left_chi": 64, + "raw_left_params": 27592, + "raw_right_chi": 64, + "raw_right_params": 27592, + "rho_max": 8.0, + "right_chi": 40, + "right_input_sampled_relative_l2": 2.2322759981295966e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.1496655004092719 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.593427034, + "wall_times_secs": [ + 0.593427034 + ], + "max_error": 4.365438227323841e-6, + "input_max_bond_dim": 41, + "output_max_bond_dim": 48, + "output_bond_dims": [ + 48 + ], + "n_params": 11740, + "n_patches": 1, + "max_patch_bond": 48, + "rtol": 1e-6, + "input_build_secs": 167.590778715 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi64.json b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi64.json new file mode 100644 index 0000000..ce3f964 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_elementwise-patched_fit-chi64.json @@ -0,0 +1,58 @@ +{ + "schema_version": 1, + "case": "gaussian_elementwise", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.8485281374238572, + "cache_hit": false, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n128-r9-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 927.013950836, + "input_compression_secs": 0.017406887, + "input_l2_rtol": 1e-6, + "input_max_patch_chi": 64, + "input_params": 43200, + "input_patch_count": 2, + "input_patch_params": 43200, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 64, + "left_input_sampled_relative_l2": 2.168208907580374e-6, + "n_gauss": 128, + "patch_build_secs": 0.786904454, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 9, + "raw_left_chi": 99, + "raw_left_params": 62240, + "raw_right_chi": 98, + "raw_right_params": 60416, + "rho_max": 8.0, + "right_chi": 64, + "right_input_sampled_relative_l2": 2.8526224091517408e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.08061099039992307 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 4.083925509, + "wall_times_secs": [ + 4.083925509 + ], + "max_error": 3.1360948802586216e-6, + "input_max_bond_dim": 64, + "output_max_bond_dim": 64, + "output_bond_dims": [ + 64 + ], + "n_params": 28028, + "n_patches": 1, + "max_patch_bond": 64, + "rtol": 1e-6, + "input_build_secs": 927.013950836 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi16.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi16.json new file mode 100644 index 0000000..ae891a0 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi16.json @@ -0,0 +1,62 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.10606601717798216, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n2-r6-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.011060636, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.030883943, + "input_l2_rtol": 1e-6, + "input_params": 3740, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 16, + "left_input_max_patch_chi": 16, + "left_input_patch_count": 1, + "left_input_patch_params": 2008, + "left_input_sampled_relative_l2": 1.2777851917357638e-6, + "n_gauss": 2, + "patch_build_secs": 0.051449814, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 6, + "raw_left_chi": 32, + "raw_left_params": 4640, + "raw_right_chi": 26, + "raw_right_params": 3872, + "rho_max": 8.0, + "right_chi": 16, + "right_input_max_patch_chi": 16, + "right_input_patch_count": 1, + "right_input_patch_params": 1732, + "right_input_sampled_relative_l2": 9.42870060096915e-7, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.021572244, + "wall_times_secs": [ + 0.021572244 + ], + "max_error": 5.942626353187935e-7, + "input_max_bond_dim": 16, + "output_max_bond_dim": 16, + "output_bond_dims": [ + 4, + 16, + 15, + 10, + 4 + ], + "n_params": 2008, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi24.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi24.json new file mode 100644 index 0000000..e718203 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi24.json @@ -0,0 +1,63 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.2121320343559643, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n8-r7-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0090007, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.004209355, + "input_l2_rtol": 1e-6, + "input_params": 7924, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 23, + "left_input_max_patch_chi": 23, + "left_input_patch_count": 1, + "left_input_patch_params": 3900, + "left_input_sampled_relative_l2": 1.7758182520386608e-6, + "n_gauss": 8, + "patch_build_secs": 0.067008984, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 7, + "raw_left_chi": 50, + "raw_left_params": 12720, + "raw_right_chi": 50, + "raw_right_params": 12720, + "rho_max": 8.0, + "right_chi": 24, + "right_input_max_patch_chi": 24, + "right_input_patch_count": 1, + "right_input_patch_params": 4024, + "right_input_sampled_relative_l2": 1.4847849136070642e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.046197985, + "wall_times_secs": [ + 0.046197985 + ], + "max_error": 7.317874531552492e-7, + "input_max_bond_dim": 24, + "output_max_bond_dim": 21, + "output_bond_dims": [ + 4, + 16, + 21, + 15, + 10, + 4 + ], + "n_params": 3652, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi41.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi41.json new file mode 100644 index 0000000..353f9e3 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi41.json @@ -0,0 +1,64 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.4242640687119286, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n32-r8-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.010558389, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.007757739, + "input_l2_rtol": 1e-6, + "input_params": 18380, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 41, + "left_input_max_patch_chi": 41, + "left_input_patch_count": 1, + "left_input_patch_params": 9272, + "left_input_sampled_relative_l2": 1.8640164827991147e-6, + "n_gauss": 32, + "patch_build_secs": 0.094807218, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 8, + "raw_left_chi": 64, + "raw_left_params": 27592, + "raw_right_chi": 64, + "raw_right_params": 27592, + "rho_max": 8.0, + "right_chi": 40, + "right_input_max_patch_chi": 40, + "right_input_patch_count": 1, + "right_input_patch_params": 9108, + "right_input_sampled_relative_l2": 2.2322759981295966e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.093783934, + "wall_times_secs": [ + 0.093783934 + ], + "max_error": 1.343038512451883e-6, + "input_max_bond_dim": 41, + "output_max_bond_dim": 34, + "output_bond_dims": [ + 4, + 16, + 34, + 21, + 15, + 10, + 4 + ], + "n_params": 7340, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi64.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi64.json new file mode 100644 index 0000000..9b37ce3 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-global_fit-chi64.json @@ -0,0 +1,65 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "global_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.8485281374238572, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n128-r9-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.013630578, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.017763551, + "input_l2_rtol": 1e-6, + "input_params": 43200, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 64, + "left_input_max_patch_chi": 64, + "left_input_patch_count": 1, + "left_input_patch_params": 22184, + "left_input_sampled_relative_l2": 2.168208907580374e-6, + "n_gauss": 128, + "patch_build_secs": 0.143642468, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 9, + "raw_left_chi": 99, + "raw_left_params": 62240, + "raw_right_chi": 98, + "raw_right_params": 60416, + "rho_max": 8.0, + "right_chi": 64, + "right_input_max_patch_chi": 64, + "right_input_patch_count": 1, + "right_input_patch_params": 21016, + "right_input_sampled_relative_l2": 2.8526224091517408e-6, + "sigma_minor": 0.05, + "spacing": 3.0 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.435669727, + "wall_times_secs": [ + 0.435669727 + ], + "max_error": 1.52521377085579e-6, + "input_max_bond_dim": 64, + "output_max_bond_dim": 59, + "output_bond_dims": [ + 4, + 16, + 59, + 36, + 21, + 15, + 10, + 4 + ], + "n_params": 17604, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi16.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi16.json new file mode 100644 index 0000000..297c421 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi16.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.10606601717798216, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n2-r6-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.011060636, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.030883943, + "input_l2_rtol": 1e-6, + "input_params": 3740, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 16, + "left_input_max_patch_chi": 16, + "left_input_patch_count": 1, + "left_input_patch_params": 2008, + "left_input_sampled_relative_l2": 1.2777851917357638e-6, + "n_gauss": 2, + "patch_build_secs": 0.051449814, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 6, + "raw_left_chi": 32, + "raw_left_params": 4640, + "raw_right_chi": 26, + "raw_right_params": 3872, + "rho_max": 8.0, + "right_chi": 16, + "right_input_max_patch_chi": 16, + "right_input_patch_count": 1, + "right_input_patch_params": 1732, + "right_input_sampled_relative_l2": 9.42870060096915e-7, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.9395868025175693 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.022959288, + "wall_times_secs": [ + 0.022959288 + ], + "max_error": 5.942626369966527e-7, + "input_max_bond_dim": 16, + "output_max_bond_dim": 16, + "output_bond_dims": [ + 16 + ], + "n_params": 2008, + "n_patches": 1, + "max_patch_bond": 16, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi24.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi24.json new file mode 100644 index 0000000..ce57a6f --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi24.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.2121320343559643, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n8-r7-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.0090007, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.004209355, + "input_l2_rtol": 1e-6, + "input_params": 7924, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 23, + "left_input_max_patch_chi": 23, + "left_input_patch_count": 1, + "left_input_patch_params": 3900, + "left_input_sampled_relative_l2": 1.7758182520386608e-6, + "n_gauss": 8, + "patch_build_secs": 0.067008984, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 7, + "raw_left_chi": 50, + "raw_left_params": 12720, + "raw_right_chi": 50, + "raw_right_params": 12720, + "rho_max": 8.0, + "right_chi": 24, + "right_input_max_patch_chi": 24, + "right_input_patch_count": 1, + "right_input_patch_params": 4024, + "right_input_sampled_relative_l2": 1.4847849136070642e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.9492824940111428 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.048666214, + "wall_times_secs": [ + 0.048666214 + ], + "max_error": 7.317874514555467e-7, + "input_max_bond_dim": 24, + "output_max_bond_dim": 21, + "output_bond_dims": [ + 21 + ], + "n_params": 3652, + "n_patches": 1, + "max_patch_bond": 21, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi41.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi41.json new file mode 100644 index 0000000..419f734 --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi41.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.4242640687119286, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n32-r8-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.010558389, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.007757739, + "input_l2_rtol": 1e-6, + "input_params": 18380, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 41, + "left_input_max_patch_chi": 41, + "left_input_patch_count": 1, + "left_input_patch_params": 9272, + "left_input_sampled_relative_l2": 1.8640164827991147e-6, + "n_gauss": 32, + "patch_build_secs": 0.094807218, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 8, + "raw_left_chi": 64, + "raw_left_params": 27592, + "raw_right_chi": 64, + "raw_right_params": 27592, + "rho_max": 8.0, + "right_chi": 40, + "right_input_max_patch_chi": 40, + "right_input_patch_count": 1, + "right_input_patch_params": 9108, + "right_input_sampled_relative_l2": 2.2322759981295966e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 0.9554049764099848 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.098161446, + "wall_times_secs": [ + 0.098161446 + ], + "max_error": 1.7733014479539222e-6, + "input_max_bond_dim": 41, + "output_max_bond_dim": 33, + "output_bond_dims": [ + 33 + ], + "n_params": 7192, + "n_patches": 1, + "max_patch_bond": 33, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi64.json b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi64.json new file mode 100644 index 0000000..dcfaa1e --- /dev/null +++ b/result/linux-epyc-7713p/raw/gaussian_mpo_contraction-patched_fit-chi64.json @@ -0,0 +1,61 @@ +{ + "schema_version": 1, + "case": "gaussian_mpo_contraction", + "algorithm": "patched_fit", + "params": { + "addition_tolerance": 1e-10, + "box_l": 0.8485281374238572, + "cache_hit": true, + "cache_key": "interpolative-gaussian-pair-v2-rev9e9aedaebe0d3918b34dd399ff0981e337f3835b-n128-r9-sigma3fa999999999999a-rho4020000000000000-spacing4008000000000000-degree28-interp3ddb7cdfd9d7bdbb-add3ddb7cdfd9d7bdbb-seed0", + "cache_load_secs": 0.013630578, + "error_samples": 256, + "external_error_metric": "sampled_relative_l2", + "input_build_secs": 0.0, + "input_compression_secs": 0.017763551, + "input_l2_rtol": 1e-6, + "input_params": 43200, + "internal_tolerance": 1e-6, + "internal_tolerance_metric": "relative_l2_svd", + "interpolation_tolerance": 1e-10, + "left_chi": 64, + "left_input_max_patch_chi": 64, + "left_input_patch_count": 1, + "left_input_patch_params": 22184, + "left_input_sampled_relative_l2": 2.168208907580374e-6, + "n_gauss": 128, + "patch_build_secs": 0.143642468, + "patch_cap": 128, + "polynomial_degree": 28, + "r": 9, + "raw_left_chi": 99, + "raw_left_params": 62240, + "raw_right_chi": 98, + "raw_right_params": 60416, + "rho_max": 8.0, + "right_chi": 64, + "right_input_max_patch_chi": 64, + "right_input_patch_count": 1, + "right_input_patch_params": 21016, + "right_input_sampled_relative_l2": 2.8526224091517408e-6, + "sigma_minor": 0.05, + "spacing": 3.0, + "speedup_vs_global": 1.4555888997409872 + }, + "seed": 0, + "tolerance": 1e-6, + "wall_time_median_secs": 0.299308223, + "wall_times_secs": [ + 0.299308223 + ], + "max_error": 2.108072658709354e-6, + "input_max_bond_dim": 64, + "output_max_bond_dim": 58, + "output_bond_dims": [ + 58 + ], + "n_params": 16764, + "n_patches": 1, + "max_patch_bond": 58, + "rtol": 1e-6, + "input_build_secs": 0.0 +} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n100000-chi900.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n100000-chi900.json deleted file mode 100644 index cb5b975..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n100000-chi900.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "box_l": 23.71708245126285, - "box_padding": 1.0, - "case": "mpo_mpo_aniso_input", - "input_add_rtol": 1e-10, - "input_build_secs": 1568.202631011, - "input_cache_hit": false, - "input_cache_key": "aniso-v5-tci-n100000-r12-e0-s4008000000000000-p3ff0000000000000-sig3fa999999999999a-rho4020000000000000-tol3e45798ee2308c3a-loc3d719799812dea11-piv8-cap3072-seed0", - "input_cache_load_secs": 0.0, - "input_chi": 900, - "input_compression_secs": 9.464503739, - "input_error_samples": 256, - "input_generator": "tci", - "input_params": [ - 3450320, - 3454660 - ], - "input_patch_counts": [ - 120, - 120 - ], - "input_patch_max_bonds": [ - 120, - 121 - ], - "input_patch_params": [ - 9866732, - 9982956 - ], - "input_poly_degree": 28, - "input_sampled_relative_errors": [ - 3.0555493578220235e-6, - 3.7404138963447223e-6 - ], - "input_sanity": 0.0001, - "input_svd_l2_rtol": 1e-6, - "input_tci_cap": 3072, - "input_tci_initial_pivots": 8, - "input_tci_local_abs_tol": 1e-12, - "input_tci_rtol": 1e-8, - "max_input_chi": 1400, - "n_gauss": 100000, - "np_over_chi_squared": [ - 4.2596543209876545, - 4.265012345679012 - ], - "patch_cap": 128, - "r": 12, - "r_extra": 0, - "raw_input_chi": 1074, - "raw_input_params": [ - 7305760, - 7308792 - ], - "rho_max": 8.0, - "seed": 0, - "sigma": 0.05, - "spacing": 3.0 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n125000-chi900.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n125000-chi900.json deleted file mode 100644 index 354302b..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n125000-chi900.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "box_l": 26.516504294495537, - "box_padding": 1.0, - "case": "mpo_mpo_aniso_input", - "input_add_rtol": 1e-10, - "input_build_secs": 2539.628990155, - "input_cache_hit": false, - "input_cache_key": "aniso-v5-tci-n125000-r13-e0-s4008000000000000-p3ff0000000000000-sig3fa999999999999a-rho4020000000000000-tol3e45798ee2308c3a-loc3d719799812dea11-piv8-cap3584-seed0", - "input_cache_load_secs": 0.0, - "input_chi": 900, - "input_compression_secs": 13.723229085, - "input_error_samples": 256, - "input_generator": "tci", - "input_params": [ - 4120944, - 4113404 - ], - "input_patch_counts": [ - 120, - 120 - ], - "input_patch_max_bonds": [ - 121, - 123 - ], - "input_patch_params": [ - 11553076, - 11596696 - ], - "input_poly_degree": 28, - "input_sampled_relative_errors": [ - 5.5092801319520735e-6, - 9.140267928712483e-6 - ], - "input_sanity": 0.0001, - "input_svd_l2_rtol": 1e-6, - "input_tci_cap": 3584, - "input_tci_initial_pivots": 8, - "input_tci_local_abs_tol": 1e-12, - "input_tci_rtol": 1e-8, - "max_input_chi": 1400, - "n_gauss": 125000, - "np_over_chi_squared": [ - 5.087585185185185, - 5.078276543209877 - ], - "patch_cap": 128, - "r": 13, - "r_extra": 0, - "raw_input_chi": 1342, - "raw_input_params": [ - 9424632, - 9396972 - ], - "rho_max": 8.0, - "seed": 0, - "sigma": 0.05, - "spacing": 3.0 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n20480-chi458.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n20480-chi458.json deleted file mode 100644 index 7e164ee..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n20480-chi458.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "box_l": 10.733126291998992, - "box_padding": 1.0, - "case": "mpo_mpo_aniso_input", - "input_add_rtol": 1e-10, - "input_build_secs": 263.992662118, - "input_cache_hit": false, - "input_cache_key": "aniso-v5-tci-n20480-r11-e0-s4008000000000000-p3ff0000000000000-sig3fa999999999999a-rho4020000000000000-tol3e45798ee2308c3a-loc3d719799812dea11-piv8-cap1280-seed0", - "input_cache_load_secs": 0.0, - "input_chi": 458, - "input_compression_secs": 1.802141383, - "input_error_samples": 256, - "input_generator": "tci", - "input_params": [ - 888076, - 886408 - ], - "input_patch_counts": [ - 30, - 30 - ], - "input_patch_max_bonds": [ - 121, - 121 - ], - "input_patch_params": [ - 1775032, - 1772136 - ], - "input_poly_degree": 28, - "input_sampled_relative_errors": [ - 2.7528033675655293e-6, - 6.954288054456006e-6 - ], - "input_sanity": 0.0001, - "input_svd_l2_rtol": 1e-6, - "input_tci_cap": 1280, - "input_tci_initial_pivots": 8, - "input_tci_local_abs_tol": 1e-12, - "input_tci_rtol": 1e-8, - "max_input_chi": 1400, - "n_gauss": 20480, - "np_over_chi_squared": [ - 4.2336911958200645, - 4.2257394023760035 - ], - "patch_cap": 128, - "r": 11, - "r_extra": 0, - "raw_input_chi": 889, - "raw_input_params": [ - 2315988, - 2322644 - ], - "rho_max": 8.0, - "seed": 0, - "sigma": 0.05, - "spacing": 3.0 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n4096-chi256.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n4096-chi256.json deleted file mode 100644 index 7c2b5ca..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n4096-chi256.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "box_l": 4.800000000000001, - "box_padding": 1.0, - "case": "mpo_mpo_aniso_input", - "input_add_rtol": 1e-10, - "input_build_secs": 46.359608388, - "input_cache_hit": false, - "input_cache_key": "aniso-v5-tci-n4096-r10-e0-s4008000000000000-p3ff0000000000000-sig3fa999999999999a-rho4020000000000000-tol3e45798ee2308c3a-loc3d719799812dea11-piv8-cap512-seed0", - "input_cache_load_secs": 0.0, - "input_chi": 256, - "input_compression_secs": 0.288869464, - "input_error_samples": 256, - "input_generator": "tci", - "input_params": [ - 254476, - 255736 - ], - "input_patch_counts": [ - 6, - 6 - ], - "input_patch_max_bonds": [ - 124, - 124 - ], - "input_patch_params": [ - 352704, - 352088 - ], - "input_poly_degree": 28, - "input_sampled_relative_errors": [ - 1.781935608908162e-6, - 3.3819348731372854e-6 - ], - "input_sanity": 0.0001, - "input_svd_l2_rtol": 1e-6, - "input_tci_cap": 512, - "input_tci_initial_pivots": 8, - "input_tci_local_abs_tol": 1e-12, - "input_tci_rtol": 1e-8, - "max_input_chi": 1400, - "n_gauss": 4096, - "np_over_chi_squared": [ - 3.88299560546875, - 3.9022216796875 - ], - "patch_cap": 128, - "r": 10, - "r_extra": 0, - "raw_input_chi": 280, - "raw_input_params": [ - 510520, - 522008 - ], - "rho_max": 8.0, - "seed": 0, - "sigma": 0.05, - "spacing": 3.0 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n512-chi89.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n512-chi89.json deleted file mode 100644 index 2afb4c1..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_input-tci-n512-chi89.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "box_l": 1.6970562748477145, - "box_padding": 1.0, - "case": "mpo_mpo_aniso_input", - "input_add_rtol": 1e-10, - "input_build_secs": 5.078735227, - "input_cache_hit": false, - "input_cache_key": "aniso-v5-tci-n512-r9-e0-s4008000000000000-p3ff0000000000000-sig3fa999999999999a-rho4020000000000000-tol3e45798ee2308c3a-loc3d719799812dea11-piv8-cap512-seed0", - "input_cache_load_secs": 0.0, - "input_chi": 89, - "input_compression_secs": 0.082263936, - "input_error_samples": 256, - "input_generator": "tci", - "input_params": [ - 48060, - 47608 - ], - "input_patch_counts": [ - 1, - 1 - ], - "input_patch_max_bonds": [ - 84, - 84 - ], - "input_patch_params": [ - 45056, - 45056 - ], - "input_poly_degree": 28, - "input_sampled_relative_errors": [ - 3.3550290079883713e-6, - 2.5588681566275107e-6 - ], - "input_sanity": 0.0001, - "input_svd_l2_rtol": 1e-6, - "input_tci_cap": 512, - "input_tci_initial_pivots": 8, - "input_tci_local_abs_tol": 1e-12, - "input_tci_rtol": 1e-8, - "max_input_chi": 1400, - "n_gauss": 512, - "np_over_chi_squared": [ - 6.067415730337078, - 6.010352228254009 - ], - "patch_cap": 128, - "r": 9, - "r_extra": 0, - "raw_input_chi": 181, - "raw_input_params": [ - 133328, - 132608 - ], - "rho_max": 8.0, - "seed": 0, - "sigma": 0.05, - "spacing": 3.0 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi128.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi128.json deleted file mode 100644 index f664c9a..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi128.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "global_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 128, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap128-seed0", - "input_cache_load_secs": 0.028256491, - "input_patch_cap": 128, - "input_patch_counts": [ - 1, - 1 - ], - "input_patch_max_bonds": [ - 128, - 128 - ], - "input_tci_cap": 128, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 3.576332009, - "wall_times_secs": [ - 3.576332009, - 3.514710307 - ], - "max_error": 0.0003454729475465829, - "input_max_bond_dim": 128, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 30, - 15, - 9, - 6, - 3 - ], - "n_params": 36336, - "rtol": 1e-8, - "input_build_secs": 1.185248102 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi192.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi192.json deleted file mode 100644 index 03ffe39..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi192.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "global_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 192, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap192-seed0", - "input_cache_load_secs": 0.031952882, - "input_patch_cap": 128, - "input_patch_counts": [ - 8, - 8 - ], - "input_patch_max_bonds": [ - 123, - 123 - ], - "input_tci_cap": 192, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 11.79123273, - "wall_times_secs": [ - 11.79123273, - 11.682349005 - ], - "max_error": 0.0004383987773122374, - "input_max_bond_dim": 192, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 31, - 15, - 9, - 6, - 3 - ], - "n_params": 36708, - "rtol": 1e-8, - "input_build_secs": 6.63499393 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi224.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi224.json deleted file mode 100644 index db6a2a8..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi224.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "global_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 224, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap224-seed0", - "input_cache_load_secs": 0.032833929, - "input_patch_cap": 128, - "input_patch_counts": [ - 8, - 8 - ], - "input_patch_max_bonds": [ - 121, - 121 - ], - "input_tci_cap": 224, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 15.468127432, - "wall_times_secs": [ - 15.347890068, - 15.468127432 - ], - "max_error": 0.0004367723269018427, - "input_max_bond_dim": 224, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 31, - 15, - 9, - 6, - 3 - ], - "n_params": 36708, - "rtol": 1e-8, - "input_build_secs": 6.446811312 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi256.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi256.json deleted file mode 100644 index 7cb7476..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-global_fit_treetn-n2048-chi256.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "global_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 256, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap384-seed0", - "input_cache_load_secs": 0.034797543, - "input_patch_cap": 128, - "input_patch_counts": [ - 8, - 8 - ], - "input_patch_max_bonds": [ - 119, - 120 - ], - "input_tci_cap": 384, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 19.606482696, - "wall_times_secs": [ - 19.606482696, - 19.557511476 - ], - "max_error": 0.0004394615152723373, - "input_max_bond_dim": 256, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 31, - 15, - 9, - 6, - 3 - ], - "n_params": 36708, - "rtol": 1e-8, - "input_build_secs": 6.272382668 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi128.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi128.json deleted file mode 100644 index a347dcb..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi128.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "patched_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 128, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap128-seed0", - "input_cache_load_secs": 0.028256491, - "input_patch_cap": 128, - "input_patch_counts": [ - 1, - 1 - ], - "input_patch_max_bonds": [ - 128, - 128 - ], - "input_tci_cap": 128, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 3.321234724, - "wall_times_secs": [ - 3.321234724, - 3.292352661 - ], - "max_error": 0.0003454900427644558, - "input_max_bond_dim": 128, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 30, - 15, - 9, - 6, - 3 - ], - "n_patches": 1, - "max_patch_bond": 78, - "rtol": 1e-8, - "input_build_secs": 1.185248102 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi192.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi192.json deleted file mode 100644 index 22de149..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi192.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "patched_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 192, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap192-seed0", - "input_cache_load_secs": 0.031952882, - "input_patch_cap": 128, - "input_patch_counts": [ - 8, - 8 - ], - "input_patch_max_bonds": [ - 123, - 123 - ], - "input_tci_cap": 192, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 13.352732666, - "wall_times_secs": [ - 13.352732666, - 13.243957682 - ], - "max_error": 0.0005547409992032523, - "input_max_bond_dim": 192, - "output_max_bond_dim": 68, - "output_bond_dims": [ - 4, - 16, - 64, - 68, - 28, - 15, - 8, - 6, - 3 - ], - "n_patches": 1, - "max_patch_bond": 68, - "rtol": 1e-8, - "input_build_secs": 6.63499393 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi224.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi224.json deleted file mode 100644 index 7f2e047..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi224.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "patched_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 224, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap224-seed0", - "input_cache_load_secs": 0.032833929, - "input_patch_cap": 128, - "input_patch_counts": [ - 8, - 8 - ], - "input_patch_max_bonds": [ - 121, - 121 - ], - "input_tci_cap": 224, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 13.102732971, - "wall_times_secs": [ - 13.073508836, - 13.102732971 - ], - "max_error": 0.0004916712233304541, - "input_max_bond_dim": 224, - "output_max_bond_dim": 68, - "output_bond_dims": [ - 4, - 16, - 64, - 68, - 28, - 15, - 8, - 6, - 3 - ], - "n_patches": 1, - "max_patch_bond": 68, - "rtol": 1e-8, - "input_build_secs": 6.446811312 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi256.json b/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi256.json deleted file mode 100644 index 4303bd0..0000000 --- a/result/linux-epyc-7713p/raw/mpo_mpo_aniso_patched-patched_fit_treetn-n2048-chi256.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_aniso_patched", - "algorithm": "patched_fit_treetn", - "params": { - "box_l": 3.394112549695429, - "box_padding": 1.0, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "error_metric": "max_rel_vs_quantics_grid_reference", - "error_seed": 99, - "fit_nfullsweeps": 1, - "global_contract_max_bond": 256, - "inner_l": 3.394112549695429, - "input_cache_hit": true, - "input_cache_key": "aniso-mpo-v1-n2048-r10-extra0-spacing4008000000000000-padding3ff0000000000000-inner400b27247aff1491-box400b27247aff1491-sigma3fa999999999999a-rho4020000000000000-rtol3e45798ee2308c3a-cap384-seed0", - "input_cache_load_secs": 0.034797543, - "input_patch_cap": 128, - "input_patch_counts": [ - 8, - 8 - ], - "input_patch_max_bonds": [ - 119, - 120 - ], - "input_tci_cap": 384, - "n_error_samples": 128, - "n_gauss": 2048, - "patched_contract_max_bond": 128, - "r": 10, - "r_extra": 0, - "rho_max": 8.0, - "runs": 2, - "sigma": 0.05, - "spacing": 3.0, - "split_strategy": "sequential_y_first", - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 12.273990265, - "wall_times_secs": [ - 12.273990265, - 12.095820478 - ], - "max_error": 0.0006281323596457093, - "input_max_bond_dim": 256, - "output_max_bond_dim": 68, - "output_bond_dims": [ - 4, - 16, - 64, - 68, - 28, - 15, - 8, - 6, - 3 - ], - "n_patches": 1, - "max_patch_bond": 68, - "rtol": 1e-8, - "input_build_secs": 6.272382668 -} \ No newline at end of file diff --git a/result/linux-epyc-7713p/report.md b/result/linux-epyc-7713p/report.md new file mode 100644 index 0000000..116889f --- /dev/null +++ b/result/linux-epyc-7713p/report.md @@ -0,0 +1,70 @@ +# Tensor4all benchmark results + +Profile: `linux-epyc-7713p`. CPU: AMD EPYC 7713P 64-Core Processor. Threads: 1. CPU affinity: 0. Source revision: `4ed4ba6597639797b9f622cb7c5ab429e7b92647`. tensor4all-rs revision: `9e9aedaebe0d3918b34dd399ff0981e337f3835b`. + +The source revision identifies the clean code that was measured. The commit adding these generated records necessarily follows that revision. + +All timings exclude input construction, cache I/O, format conversion, patch preparation, output conversion and accuracy evaluation. Gaussian inputs use independent two-dimensional interpolative decompositions, balanced pairwise addition, final relative-L2/SVD tolerance `1e-6`, and fixed patch cap 128. + +## Case 1: Fourier elementwise + +| input χ | K | arm | time (s) | sampled relative L2 | output χ | parameters | +|---:|---:|---|---:|---:|---:|---:| +| 5 | 4 | aci | 0.073347 | 1.163e-08 | 9 | 1026 | +| 5 | 4 | fit | 0.078786 | 1.213e-08 | 8 | 606 | +| 5 | 4 | naive | 0.001891 | 1.211e-08 | 8 | 606 | +| 5 | 4 | zipup | 0.036320 | 1.197e-08 | 8 | 606 | +| 8 | 8 | aci | 0.077033 | 8.173e-09 | 15 | 1628 | +| 8 | 8 | fit | 0.080764 | 1.066e-08 | 8 | 726 | +| 8 | 8 | naive | 0.002576 | 1.066e-08 | 8 | 726 | +| 8 | 8 | zipup | 0.037141 | 1.080e-08 | 8 | 726 | +| 8 | 16 | aci | 0.072607 | 6.089e-09 | 16 | 2206 | +| 8 | 16 | fit | 0.085960 | 1.620e-08 | 10 | 900 | +| 8 | 16 | naive | 0.003332 | 1.620e-08 | 10 | 900 | +| 8 | 16 | zipup | 0.038438 | 1.636e-08 | 10 | 900 | +| 11 | 32 | aci | 0.080893 | 4.939e-09 | 22 | 3324 | +| 11 | 32 | fit | 0.087356 | 1.806e-08 | 13 | 1200 | +| 11 | 32 | naive | 0.006156 | 1.806e-08 | 13 | 1200 | +| 11 | 32 | zipup | 0.038147 | 2.001e-08 | 13 | 1182 | +| 14 | 64 | aci | 0.080989 | 4.480e-09 | 29 | 4752 | +| 14 | 64 | fit | 0.096748 | 1.813e-08 | 16 | 1638 | +| 14 | 64 | naive | 0.009583 | 1.813e-08 | 16 | 1638 | +| 14 | 64 | zipup | 0.044973 | 1.856e-08 | 16 | 1638 | +| 16 | 128 | aci | 0.089005 | 3.255e-09 | 32 | 6728 | +| 16 | 128 | fit | 0.094404 | 1.044e-08 | 18 | 2258 | +| 16 | 128 | naive | 0.016861 | 1.044e-08 | 18 | 2258 | +| 16 | 128 | zipup | 0.044607 | 1.064e-08 | 18 | 2258 | + +## Case 2: Gaussian elementwise, global versus patched + +| input χ | raw χ | N | R | arm | time (s) | sampled relative L2 | input patches | input max patch χ | output patches | parameters | speedup | +|---:|---:|---:|---:|---|---:|---:|---:|---:|---:|---:|---:| +| 16 | 32 | 2 | 6 | global_aci | 0.008655 | 1.398e-06 | 2 | 16 | 1 | 6560 | 1.000 | +| 16 | 32 | 2 | 6 | global_fit | 0.028473 | 2.293e-06 | 2 | 16 | 1 | 2300 | 1.000 | +| 16 | 32 | 2 | 6 | patched_aci | 0.021844 | 2.292e-06 | 2 | 16 | 1 | 2300 | 0.396 | +| 16 | 32 | 2 | 6 | patched_fit | 0.044864 | 2.292e-06 | 2 | 16 | 1 | 2300 | 0.635 | +| 24 | 50 | 8 | 7 | global_aci | 0.019403 | 2.942e-06 | 2 | 24 | 1 | 23268 | 1.000 | +| 24 | 50 | 8 | 7 | global_fit | 0.042136 | 3.462e-06 | 2 | 24 | 1 | 4776 | 1.000 | +| 24 | 50 | 8 | 7 | patched_aci | 0.270262 | 3.459e-06 | 2 | 24 | 1 | 4908 | 0.072 | +| 24 | 50 | 8 | 7 | patched_fit | 0.112770 | 3.459e-06 | 2 | 24 | 1 | 4908 | 0.374 | +| 41 | 64 | 32 | 8 | global_aci | 0.065374 | 3.468e-06 | 2 | 41 | 1 | 98992 | 1.000 | +| 41 | 64 | 32 | 8 | global_fit | 0.088816 | 4.661e-06 | 2 | 41 | 1 | 11072 | 1.000 | +| 41 | 64 | 32 | 8 | patched_aci | 2.430336 | 4.366e-06 | 2 | 41 | 1 | 11740 | 0.027 | +| 41 | 64 | 32 | 8 | patched_fit | 0.593427 | 4.365e-06 | 2 | 41 | 1 | 11740 | 0.150 | +| 64 | 99 | 128 | 9 | global_aci | 0.212690 | 2.705e-06 | 2 | 64 | 1 | 317712 | 1.000 | +| 64 | 99 | 128 | 9 | global_fit | 0.329209 | 3.993e-06 | 2 | 64 | 1 | 25476 | 1.000 | +| 64 | 99 | 128 | 9 | patched_aci | 8.942323 | 3.168e-06 | 2 | 64 | 1 | 28028 | 0.024 | +| 64 | 99 | 128 | 9 | patched_fit | 4.083926 | 3.136e-06 | 2 | 64 | 1 | 28028 | 0.081 | + +## Case 3: Gaussian MPO-MPO contraction, global versus patched + +| input χ | raw χ | N | R | arm | time (s) | sampled relative L2 | input patches | input max patch χ | output patches | parameters | speedup | +|---:|---:|---:|---:|---|---:|---:|---:|---:|---:|---:|---:| +| 16 | 32 | 2 | 6 | global_fit | 0.021572 | 5.943e-07 | 2 | 16 | 1 | 2008 | 1.000 | +| 16 | 32 | 2 | 6 | patched_fit | 0.022959 | 5.943e-07 | 2 | 16 | 1 | 2008 | 0.940 | +| 24 | 50 | 8 | 7 | global_fit | 0.046198 | 7.318e-07 | 2 | 24 | 1 | 3652 | 1.000 | +| 24 | 50 | 8 | 7 | patched_fit | 0.048666 | 7.318e-07 | 2 | 24 | 1 | 3652 | 0.949 | +| 41 | 64 | 32 | 8 | global_fit | 0.093784 | 1.343e-06 | 2 | 41 | 1 | 7340 | 1.000 | +| 41 | 64 | 32 | 8 | patched_fit | 0.098161 | 1.773e-06 | 2 | 41 | 1 | 7192 | 0.955 | +| 64 | 99 | 128 | 9 | global_fit | 0.435670 | 1.525e-06 | 2 | 64 | 1 | 17604 | 1.000 | +| 64 | 99 | 128 | 9 | patched_fit | 0.299308 | 2.108e-06 | 2 | 64 | 1 | 16764 | 1.456 | diff --git a/result/linux-epyc-7713p/run.yaml b/result/linux-epyc-7713p/run.yaml index 4295b75..f92220c 100644 --- a/result/linux-epyc-7713p/run.yaml +++ b/result/linux-epyc-7713p/run.yaml @@ -1,13 +1,9 @@ profile: linux-epyc-7713p -date: 2026-08-19T10:30:32Z -machine: linux-epyc-7713p -os: Linux x86_64 +date_utc: 2026-08-20T06:56:20Z +os: Linux chip: AMD EPYC 7713P 64-Core Processor -memory_gb: 995 -repo_rev: add289e57c9b090a10d048892746d8e396255682 -working_tree: verify/partitioned-mpo-correctness +memory_gb: 995.5 +repo_rev: 4ed4ba6597639797b9f622cb7c5ab429e7b92647 tensor4all_rs_rev: 9e9aedaebe0d3918b34dd399ff0981e337f3835b threads: 1 -cpu_affinity: 62 -runs: 2 -warmups: 0 +cpu_affinity: 0 diff --git a/result/mac-cpu/elementwise_fourier-error.svg b/result/mac-cpu/elementwise_fourier-error.svg deleted file mode 100644 index 099e003..0000000 --- a/result/mac-cpu/elementwise_fourier-error.svg +++ /dev/null @@ -1,1199 +0,0 @@ - - - - - - - - 2026-08-14T12:29:07.775710 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_fourier-time.svg b/result/mac-cpu/elementwise_fourier-time.svg deleted file mode 100644 index 3d4411d..0000000 --- a/result/mac-cpu/elementwise_fourier-time.svg +++ /dev/null @@ -1,1382 +0,0 @@ - - - - - - - - 2026-08-14T12:29:07.748120 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_fourier.md b/result/mac-cpu/elementwise_fourier.md deleted file mode 100644 index 33b11ec..0000000 --- a/result/mac-cpu/elementwise_fourier.md +++ /dev/null @@ -1,12 +0,0 @@ -# elementwise_fourier - -| algorithm | points | fitted time exponent | worst max abs error | -|---|---|---|---| -| aci | 6 | 0.31 | 3.74e-07 | -| fit | 6 | 0.99 | 6.49e-07 | -| naive | 6 | 1.86 | 6.49e-07 | -| zipup | 6 | 2.01 | 3.90e-06 | - -![time](./elementwise_fourier-time.svg) - -![error](./elementwise_fourier-error.svg) diff --git a/result/mac-cpu/elementwise_gauss2d-error.svg b/result/mac-cpu/elementwise_gauss2d-error.svg deleted file mode 100644 index f736753..0000000 --- a/result/mac-cpu/elementwise_gauss2d-error.svg +++ /dev/null @@ -1,1168 +0,0 @@ - - - - - - - - 2026-08-14T12:29:07.902736 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d-time.svg b/result/mac-cpu/elementwise_gauss2d-time.svg deleted file mode 100644 index 86e7e3b..0000000 --- a/result/mac-cpu/elementwise_gauss2d-time.svg +++ /dev/null @@ -1,1756 +0,0 @@ - - - - - - - - 2026-08-14T12:29:07.864476 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d.md b/result/mac-cpu/elementwise_gauss2d.md deleted file mode 100644 index 18477b5..0000000 --- a/result/mac-cpu/elementwise_gauss2d.md +++ /dev/null @@ -1,14 +0,0 @@ -# elementwise_gauss2d - -| algorithm | points | fitted time exponent | worst max relative error | -|---|---|---|---| -| aci | 5 | 9.48 | 2.26e-08 | -| fit_treetn | 5 | 8.42 | 2.48e-08 | -| naive | 5 | 12.10 | 2.48e-08 | -| zipup_treetn | 5 | 7.60 | 1.02e+00 | - -Note: every algorithm forms the product at the same output budget, its maximum bond dimension capped at the input rank chi, and the cap is the only truncation control: the product tolerance is pinned inert at contract_tol and the aci arm runs with a scale-relative stopping criterion, so every arm spends the whole budget unless its exact rank is smaller and the error column is the discriminator. The exact elementwise product has rank up to chi squared, so this budget is tight: naive, fit_treetn and aci stay near the working tolerance while zipup_treetn spends the whole budget and still returns an order-unity relative error. Raising the budget recovers it, so that is the price of the fixed budget rather than a broken arm. There is no simplett arm here: simplett exposes no elementwise product for tensor trains at the pinned revision, so this case cannot compare the two engines on one algorithm the way case 2 does. The engine that ran each arm is recorded as engine: local for naive, treetn for the two hadamard arms, aci for the cross interpolation. The fitted time exponent is measured against input chi along a sweep of r, where the site count also grows, so it is not a pure chi power law. - -![time](./elementwise_gauss2d-time.svg) - -![error](./elementwise_gauss2d-error.svg) diff --git a/result/mac-cpu/elementwise_gauss2d_patched-error.svg b/result/mac-cpu/elementwise_gauss2d_patched-error.svg deleted file mode 100644 index a804182..0000000 --- a/result/mac-cpu/elementwise_gauss2d_patched-error.svg +++ /dev/null @@ -1,1986 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.209911 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_patched-params-aniso.svg b/result/mac-cpu/elementwise_gauss2d_patched-params-aniso.svg deleted file mode 100644 index 34c70c9..0000000 --- a/result/mac-cpu/elementwise_gauss2d_patched-params-aniso.svg +++ /dev/null @@ -1,1661 +0,0 @@ - - - - - - - - 2026-08-14T12:29:07.967806 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_patched-params-smooth.svg b/result/mac-cpu/elementwise_gauss2d_patched-params-smooth.svg deleted file mode 100644 index 53357bd..0000000 --- a/result/mac-cpu/elementwise_gauss2d_patched-params-smooth.svg +++ /dev/null @@ -1,1594 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.048328 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_patched-time.svg b/result/mac-cpu/elementwise_gauss2d_patched-time.svg deleted file mode 100644 index 292d246..0000000 --- a/result/mac-cpu/elementwise_gauss2d_patched-time.svg +++ /dev/null @@ -1,2398 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.149459 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_patched.md b/result/mac-cpu/elementwise_gauss2d_patched.md deleted file mode 100644 index 5fd9dc7..0000000 --- a/result/mac-cpu/elementwise_gauss2d_patched.md +++ /dev/null @@ -1,120 +0,0 @@ -# elementwise_gauss2d_patched - -| algorithm | points | fitted time exponent | worst max relative error | -|---|---|---|---| -| aci (aniso) | 7 | 1.13 | 1.31e-08 | -| aci (smooth) | 4 | 1.60 | 9.34e-09 | -| fit_treetn (aniso) | 7 | 1.49 | 4.29e-08 | -| fit_treetn (smooth) | 4 | 0.43 | 3.52e-08 | -| patched_aci (aniso) | 7 | 1.16 | 4.69e-08 | -| patched_aci (smooth) | 4 | 1.05 | 4.09e-08 | -| patched_fit_treetn (aniso) | 7 | 1.25 | 4.69e-08 | -| patched_fit_treetn (smooth) | 4 | 0.88 | 3.79e-08 | -| patched_naive (aniso) | 7 | 1.49 | 4.69e-08 | -| patched_naive (smooth) | 4 | 1.00 | 3.79e-08 | - -Note: this case runs two instance families, recorded per arm as family and tabulated separately below, and it is controlled by the accuracy instead of by a fixed output budget. The default family aniso is N anisotropic narrow spikes at a fixed spacing-to-width ratio, whose random orientations and aspect ratios push the global rank toward the geometric bound of the bit count; smooth is the density-constant isotropic family of elementwise_gauss2d_scaling. Every arm is asked for the same global relative tolerance rtol, and what the case measures is the size and the time each one needs to reach it, so the arms are comparable only because rtol is the same for all of them and the error column is a check that they got there rather than the discriminator. The size metric is n_params, the total number of stored core entries: a bond dimension says nothing across the two representations here, since a patched arm holds one train per patch and no single global rank exists. For the patched arms n_params counts the free sites of each patch only, the cores at the projected sites being one-hot copy selectors that carry structure rather than data. The patched arms build each input as a partitioned tensor train, split until every patch fits under the per-patch rank cap, form the product patch pair by patch pair, and budget the result once at the end with volume-proportional absolute budgets, which is what makes shrinking patch norms harmless. Which construction split the inputs is recorded per arm as input_path: the default norm builds one global train per input and splits it by Frobenius norms, so its input_build_secs includes that global build, while tci runs a TCI per patch on the function and forms no global train at all. The two global arms fit_treetn and aci are the case-3 arms run tolerance-driven at the same rtol with no binding rank cap, and each has its own N ceiling, since the uncapped global fit is orders of magnitude more expensive than the interpolating arm. Input construction is not part of the reported wall time: it is recorded separately as input_build_secs, since one build is shared by every arm of an instance. The fitted time exponent is measured against N. - -# Family: aniso - -N anisotropic narrow spikes: minor width sigma fixed, aspect ratio log-uniform in [1, rho_max] and orientation uniform in [0, pi) drawn per spike, mean spacing held at a fixed number of minor widths so the box grows like sqrt(N) and R resolves sigma to a quarter step. This is the family the case defaults to: a field of small hard features whose global rank climbs like N^0.5 through the sweep and then decelerates toward a density-set plateau at larger N, while a patched representation is held at its per-patch cap by construction. The isotropic control of the same family, rho_max = 1, grows the same way, so the rank comes from the density of narrow features rather than from the anisotropy. - - -## Instances - -| N | box half-width L | bits per variable R | input patches f, g | input params, patched | patched build [s] | global chi_in | input params, global | global build [s] | -|---|---|---|---|---|---|---|---|---| -| 8 | 0.212 | 6 | 1, 1 | 9488 | 0.06 | 45 | 12352 | 0.03 | -| 16 | 0.300 | 6 | 1, 1 | 11712 | 0.07 | 53 | 14528 | 0.02 | -| 32 | 0.424 | 7 | 1, 1 | 29076 | 0.30 | 64 | 39040 | 0.08 | -| 64 | 0.600 | 7 | 1, 1 | 38080 | 0.40 | 64 | 43840 | 0.09 | -| 128 | 0.849 | 8 | 4, 4 | 116580 | 12.41 | 88 | 92552 | 0.46 | -| 256 | 1.200 | 8 | 4, 4 | 152000 | 29.04 | 120 | 128460 | 0.63 | -| 512 | 1.697 | 9 | 16, 16 | 456956 | 197.79 | 182 | 267264 | 2.72 | - -## Size and time at equal accuracy - -| algorithm | N | median time [s] | max relative error | params | patches | max patch bond | pairs | pairs time [s] | truncate time [s] | -|---|---|---|---|---|---|---|---|---|---| -| aci | 8 | 0.0040 | 1.31e-08 | 7456 | one train | 54 | not patched | not patched | not patched | -| aci | 16 | 0.0039 | 5.27e-09 | 8224 | one train | 60 | not patched | not patched | not patched | -| aci | 32 | 0.0119 | 6.09e-09 | 22880 | one train | 64 | not patched | not patched | not patched | -| aci | 64 | 0.0151 | 3.41e-09 | 24480 | one train | 64 | not patched | not patched | not patched | -| aci | 128 | 0.0770 | 5.78e-09 | 97168 | one train | 182 | not patched | not patched | not patched | -| aci | 256 | 0.0971 | 5.57e-09 | 116876 | one train | 213 | not patched | not patched | not patched | -| aci | 512 | 0.3868 | 4.44e-09 | 315040 | one train | 256 | not patched | not patched | not patched | -| fit_treetn | 8 | 0.0413 | 1.40e-08 | 5536 | one train | 39 | not patched | not patched | not patched | -| fit_treetn | 16 | 0.0483 | 1.52e-08 | 6560 | one train | 47 | not patched | not patched | not patched | -| fit_treetn | 32 | 0.2669 | 4.29e-08 | 17532 | one train | 63 | not patched | not patched | not patched | -| fit_treetn | 64 | 0.2856 | 1.10e-08 | 20960 | one train | 64 | not patched | not patched | not patched | -| fit_treetn | 128 | 2.2442 | 2.03e-08 | 40864 | one train | 80 | not patched | not patched | not patched | -| fit_treetn | 256 | 2.8123 | 2.06e-08 | 57584 | one train | 108 | not patched | not patched | not patched | -| fit_treetn | 512 | 20.3180 | 2.26e-08 | 118568 | one train | 169 | not patched | not patched | not patched | -| patched_aci | 8 | 0.0175 | 4.69e-08 | 5536 | 1 | 39 | 1 | 0.005 | 0.013 | -| patched_aci | 16 | 0.0165 | 2.94e-08 | 6560 | 1 | 47 | 1 | 0.004 | 0.013 | -| patched_aci | 32 | 0.1587 | 4.47e-08 | 17848 | 1 | 63 | 1 | 0.020 | 0.139 | -| patched_aci | 64 | 0.1265 | 2.10e-08 | 20960 | 1 | 64 | 1 | 0.012 | 0.115 | -| patched_aci | 128 | 0.4928 | 4.37e-08 | 70128 | 4 | 64 | 4 | 0.056 | 0.437 | -| patched_aci | 256 | 0.4888 | 2.80e-08 | 82560 | 4 | 64 | 4 | 0.047 | 0.441 | -| patched_aci | 512 | 2.2450 | 4.44e-08 | 294680 | 28 | 64 | 28 | 0.341 | 1.903 | -| patched_fit_treetn | 8 | 0.0495 | 4.69e-08 | 5536 | 1 | 39 | 1 | 0.040 | 0.010 | -| patched_fit_treetn | 16 | 0.0577 | 2.94e-08 | 6560 | 1 | 47 | 1 | 0.046 | 0.011 | -| patched_fit_treetn | 32 | 0.3043 | 4.47e-08 | 17848 | 1 | 63 | 1 | 0.220 | 0.084 | -| patched_fit_treetn | 64 | 0.3737 | 2.10e-08 | 20960 | 1 | 64 | 1 | 0.280 | 0.094 | -| patched_fit_treetn | 128 | 1.2954 | 4.37e-08 | 70128 | 4 | 64 | 4 | 0.981 | 0.314 | -| patched_fit_treetn | 256 | 1.4741 | 2.80e-08 | 82560 | 4 | 64 | 4 | 1.122 | 0.352 | -| patched_fit_treetn | 512 | 11.1820 | 4.44e-08 | 294680 | 28 | 64 | 28 | 7.938 | 3.243 | -| patched_naive | 8 | 0.0554 | 4.69e-08 | 5536 | 1 | 39 | 1 | 0.046 | 0.010 | -| patched_naive | 16 | 0.0795 | 2.94e-08 | 6560 | 1 | 47 | 1 | 0.068 | 0.011 | -| patched_naive | 32 | 0.5005 | 4.47e-08 | 17848 | 1 | 63 | 1 | 0.416 | 0.084 | -| patched_naive | 64 | 3.2924 | 2.10e-08 | 20960 | 1 | 64 | 1 | 3.194 | 0.098 | -| patched_naive | 128 | 1.8800 | 4.37e-08 | 70128 | 4 | 64 | 4 | 1.569 | 0.311 | -| patched_naive | 256 | 13.2904 | 2.80e-08 | 82560 | 4 | 64 | 4 | 12.937 | 0.353 | -| patched_naive | 512 | 17.7775 | 4.44e-08 | 294680 | 28 | 64 | 28 | 16.321 | 1.456 | - -![params](./elementwise_gauss2d_patched-params-aniso.svg) - -# Family: smooth - -N isotropic Gaussians of log-uniform inverse width at constant density, case 4's family. Smooth everywhere, so there is no hard region for the patching to isolate. - - -## Instances - -| N | box half-width L | bits per variable R | input patches f, g | input params, patched | patched build [s] | global chi_in | input params, global | global build [s] | -|---|---|---|---|---|---|---|---|---| -| 8 | 6.000 | 10 | 1, 1 | 67368 | 1.85 | 79 | 102324 | 1.01 | -| 16 | 8.485 | 11 | 4, 4 | 163644 | 26.20 | 103 | 165304 | 2.10 | -| 32 | 12.000 | 11 | 6, 7 | 234952 | 58.80 | 117 | 222852 | 2.85 | -| 64 | 16.971 | 12 | 13, 16 | 432932 | 151.59 | 143 | 325416 | 5.76 | - -## Size and time at equal accuracy - -| algorithm | N | median time [s] | max relative error | params | patches | max patch bond | pairs | pairs time [s] | truncate time [s] | -|---|---|---|---|---|---|---|---|---|---| -| aci | 8 | 0.0610 | 8.85e-09 | 52048 | one train | 76 | not patched | not patched | not patched | -| aci | 16 | 0.6077 | 4.54e-09 | 89152 | one train | 95 | not patched | not patched | not patched | -| aci | 32 | 1.0491 | 9.34e-09 | 141176 | one train | 129 | not patched | not patched | not patched | -| aci | 64 | 2.0502 | 6.23e-09 | 283624 | one train | 183 | not patched | not patched | not patched | -| fit_treetn | 8 | 19.3066 | 1.12e-08 | 34752 | one train | 61 | not patched | not patched | not patched | -| fit_treetn | 16 | 25.3535 | 1.90e-08 | 50612 | one train | 80 | not patched | not patched | not patched | -| fit_treetn | 32 | 31.4667 | 3.52e-08 | 74800 | one train | 95 | not patched | not patched | not patched | -| fit_treetn | 64 | 48.2824 | 1.50e-08 | 114024 | one train | 120 | not patched | not patched | not patched | -| patched_aci | 8 | 4.7483 | 3.79e-08 | 35952 | 1 | 63 | 1 | 0.461 | 4.287 | -| patched_aci | 16 | 7.0666 | 1.58e-08 | 106972 | 14 | 58 | 16 | 0.665 | 6.401 | -| patched_aci | 32 | 23.6959 | 3.63e-08 | 128876 | 6 | 67 | 6 | 1.389 | 22.307 | -| patched_aci | 64 | 35.7547 | 4.09e-08 | 381004 | 33 | 60 | 64 | 2.544 | 33.210 | -| patched_fit_treetn | 8 | 5.5169 | 3.79e-08 | 35952 | 1 | 63 | 1 | 4.280 | 1.237 | -| patched_fit_treetn | 16 | 19.3617 | 1.58e-08 | 106972 | 14 | 58 | 16 | 17.531 | 1.831 | -| patched_fit_treetn | 32 | 9.7015 | 3.63e-08 | 128876 | 6 | 67 | 6 | 6.530 | 3.172 | -| patched_fit_treetn | 64 | 53.6306 | 3.75e-08 | 380632 | 33 | 60 | 64 | 47.016 | 6.613 | -| patched_naive | 8 | 6.4943 | 3.79e-08 | 35952 | 1 | 63 | 1 | 5.628 | 0.866 | -| patched_naive | 16 | 11.8447 | 1.58e-08 | 106972 | 14 | 58 | 16 | 9.965 | 1.880 | -| patched_naive | 32 | 13.1915 | 3.63e-08 | 128876 | 6 | 67 | 6 | 9.999 | 3.192 | -| patched_naive | 64 | 63.0637 | 3.75e-08 | 380632 | 33 | 60 | 64 | 24.510 | 38.552 | - -![params](./elementwise_gauss2d_patched-params-smooth.svg) - -![time](./elementwise_gauss2d_patched-time.svg) - -![error](./elementwise_gauss2d_patched-error.svg) diff --git a/result/mac-cpu/elementwise_gauss2d_scaling-chi.svg b/result/mac-cpu/elementwise_gauss2d_scaling-chi.svg deleted file mode 100644 index 7b01ac9..0000000 --- a/result/mac-cpu/elementwise_gauss2d_scaling-chi.svg +++ /dev/null @@ -1,1143 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.277801 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_scaling-error.svg b/result/mac-cpu/elementwise_gauss2d_scaling-error.svg deleted file mode 100644 index d2cf77a..0000000 --- a/result/mac-cpu/elementwise_gauss2d_scaling-error.svg +++ /dev/null @@ -1,2142 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.421029 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_scaling-time.svg b/result/mac-cpu/elementwise_gauss2d_scaling-time.svg deleted file mode 100644 index 32ca42a..0000000 --- a/result/mac-cpu/elementwise_gauss2d_scaling-time.svg +++ /dev/null @@ -1,1409 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.378149 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/elementwise_gauss2d_scaling.md b/result/mac-cpu/elementwise_gauss2d_scaling.md deleted file mode 100644 index 4df0bc6..0000000 --- a/result/mac-cpu/elementwise_gauss2d_scaling.md +++ /dev/null @@ -1,26 +0,0 @@ -# elementwise_gauss2d_scaling - -| algorithm | points | fitted time exponent | worst max relative error | -|---|---|---|---| -| aci | 4 | 3.11 | 9.34e-09 | -| fit_treetn | 4 | 3.65 | 6.51e-09 | -| zipup_treetn | 4 | 3.71 | 4.75e-01 | - -Note: this case is the density-constant scaling study of elementwise_gauss2d. The number of Gaussians N is swept while the box area grows proportionally to N, box half-width L = L0 sqrt(N / N0), so the Gaussians per unit area stay fixed, and the bit count grows with the box, R = R0 + round(log2(L / L0)), so the grid spacing and hence the resolution per Gaussian stay roughly constant. The quantity of interest is the input rank chi_in as a function of N, reported in the instance table and the chi plot below. The elementwise product itself runs at the same fixed output budget chi_out <= chi_in as case 3, decided by the cap alone with an inert contract_tol. The naive arm of case 3 is excluded here: it forms the full chi_in-squared bond before truncating, which dominates the sweep at these ranks without adding a conclusion, since it tracks fit_treetn to the last reported digit in case 3. As in case 3, zipup_treetn spends the whole budget and still returns an order-unity relative error. The fitted time exponent is measured against input chi along a sweep of N, where the site count also grows, so it is not a pure chi power law. - -## Instances and input rank - -| N | box half-width L | bits per variable R | input rank chi_in | -|---|---|---|---| -| 8 | 6.000 | 10 | 79 | -| 16 | 8.485 | 11 | 102 | -| 32 | 12.000 | 11 | 117 | -| 64 | 16.971 | 12 | 139 | - -Fitted over this sweep, chi_in grows like N^x with x = 0.26, against x = 0.5 for the sqrt(N) hypothesis and x = 1 for the linear one. - -![chi](./elementwise_gauss2d_scaling-chi.svg) - -![time](./elementwise_gauss2d_scaling-time.svg) - -![error](./elementwise_gauss2d_scaling-error.svg) diff --git a/result/mac-cpu/mpo_mpo_quantics-error.svg b/result/mac-cpu/mpo_mpo_quantics-error.svg deleted file mode 100644 index 8f8febc..0000000 --- a/result/mac-cpu/mpo_mpo_quantics-error.svg +++ /dev/null @@ -1,1767 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.584599 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/mpo_mpo_quantics-time.svg b/result/mac-cpu/mpo_mpo_quantics-time.svg deleted file mode 100644 index ef5af18..0000000 --- a/result/mac-cpu/mpo_mpo_quantics-time.svg +++ /dev/null @@ -1,1705 +0,0 @@ - - - - - - - - 2026-08-14T12:29:08.542580 - image/svg+xml - - - Matplotlib v3.11.1, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-cpu/mpo_mpo_quantics.md b/result/mac-cpu/mpo_mpo_quantics.md deleted file mode 100644 index cff31aa..0000000 --- a/result/mac-cpu/mpo_mpo_quantics.md +++ /dev/null @@ -1,14 +0,0 @@ -# mpo_mpo_quantics - -| algorithm | points | fitted time exponent | worst max relative error | -|---|---|---|---| -| fit_treetn | 5 | 8.36 | 4.17e-09 | -| naive | 5 | 19.07 | 4.17e-09 | -| zipup_simplett | 5 | 7.76 | 1.05e-04 | -| zipup_treetn | 5 | 7.14 | 1.05e-04 | - -Note: every algorithm contracts at the same output budget, its maximum bond dimension capped at the input rank chi, and the cap is the only truncation control: the contraction tolerance is pinned inert at contract_tol, so every arm spends the whole budget unless its exact rank is smaller and the error column is the discriminator. naive and zipup_simplett run on the simplett engine, zipup_treetn and fit_treetn on treetn; both engines truncate relative to the largest singular value at the pinned revision. The two zipup arms are the same algorithm on the two engines, so their difference isolates the engine, and it is now confined to wall time. The fitted time exponent is measured against input chi along a sweep of r, where the site count also grows, so it is not a pure chi power law. - -![time](./mpo_mpo_quantics-time.svg) - -![error](./mpo_mpo_quantics-error.svg) diff --git a/result/mac-cpu/raw/elementwise_fourier-zipup-k128.json b/result/mac-cpu/raw/elementwise_fourier-zipup-k128.json deleted file mode 100644 index 6a9d000..0000000 --- a/result/mac-cpu/raw/elementwise_fourier-zipup-k128.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 128, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.044585125, - "wall_times_secs": [ - 0.045063083, - 0.044807083, - 0.044585125, - 0.044297916, - 0.044248583 - ], - "max_error": 3.901650788479408e-6, - "input_max_bond_dim": 16, - "output_max_bond_dim": 106, - "output_bond_dims": [ - 4, - 16, - 47, - 106, - 105, - 79, - 58, - 38, - 28, - 21, - 19, - 12, - 12, - 7, - 6, - 5, - 5, - 4, - 2 - ], - "n_params": 69294 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_fourier-zipup-k16.json b/result/mac-cpu/raw/elementwise_fourier-zipup-k16.json deleted file mode 100644 index ba83ced..0000000 --- a/result/mac-cpu/raw/elementwise_fourier-zipup-k16.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 16, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.007298167, - "wall_times_secs": [ - 0.007370333, - 0.007356083, - 0.007290667, - 0.007298167, - 0.00726575 - ], - "max_error": 1.677943787012403e-7, - "input_max_bond_dim": 8, - "output_max_bond_dim": 52, - "output_bond_dims": [ - 4, - 16, - 50, - 52, - 42, - 30, - 22, - 20, - 13, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 3, - 2 - ], - "n_params": 17658 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_fourier-zipup-k32.json b/result/mac-cpu/raw/elementwise_fourier-zipup-k32.json deleted file mode 100644 index 898254d..0000000 --- a/result/mac-cpu/raw/elementwise_fourier-zipup-k32.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 32, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.012203875, - "wall_times_secs": [ - 0.012290083, - 0.01225475, - 0.012203875, - 0.012120583, - 0.012111042 - ], - "max_error": 1.276663051436476e-7, - "input_max_bond_dim": 11, - "output_max_bond_dim": 80, - "output_bond_dims": [ - 4, - 16, - 36, - 80, - 59, - 38, - 29, - 22, - 22, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 2 - ], - "n_params": 27228 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_fourier-zipup-k4.json b/result/mac-cpu/raw/elementwise_fourier-zipup-k4.json deleted file mode 100644 index 4d3f132..0000000 --- a/result/mac-cpu/raw/elementwise_fourier-zipup-k4.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 4, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.004072417, - "wall_times_secs": [ - 0.004521125, - 0.004072417, - 0.004051083, - 0.004174583, - 0.004018375 - ], - "max_error": 5.139049218547338e-8, - "input_max_bond_dim": 5, - "output_max_bond_dim": 22, - "output_bond_dims": [ - 4, - 13, - 19, - 21, - 22, - 22, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 3, - 3, - 3, - 2 - ], - "n_params": 5158 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_fourier-zipup-k64.json b/result/mac-cpu/raw/elementwise_fourier-zipup-k64.json deleted file mode 100644 index 3677190..0000000 --- a/result/mac-cpu/raw/elementwise_fourier-zipup-k64.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 64, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.023126541, - "wall_times_secs": [ - 0.023014584, - 0.023191875, - 0.022808125, - 0.023126541, - 0.023300792 - ], - "max_error": 5.017707954136794e-7, - "input_max_bond_dim": 14, - "output_max_bond_dim": 104, - "output_bond_dims": [ - 4, - 16, - 33, - 104, - 80, - 58, - 38, - 30, - 21, - 20, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 2 - ], - "n_params": 44494 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_fourier-zipup-k8.json b/result/mac-cpu/raw/elementwise_fourier-zipup-k8.json deleted file mode 100644 index 387a255..0000000 --- a/result/mac-cpu/raw/elementwise_fourier-zipup-k8.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 8, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.006210792, - "wall_times_secs": [ - 0.006291209, - 0.006200666, - 0.006216083, - 0.006210792, - 0.006154625 - ], - "max_error": 9.541250308108335e-8, - "input_max_bond_dim": 8, - "output_max_bond_dim": 52, - "output_bond_dims": [ - 4, - 15, - 52, - 42, - 31, - 23, - 22, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 3, - 3, - 2 - ], - "n_params": 12942 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-aci-r10.json b/result/mac-cpu/raw/elementwise_gauss2d-aci-r10.json deleted file mode 100644 index bf42150..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-aci-r10.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.052458209, - "wall_times_secs": [ - 0.052591959, - 0.052234875, - 0.052458209 - ], - "max_error": 2.7180921510472197e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 96208 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-aci-r12.json b/result/mac-cpu/raw/elementwise_gauss2d-aci-r12.json deleted file mode 100644 index baa6c4a..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-aci-r12.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0168154995876453, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "ref_scale": 0.4568278674896437, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.077176125, - "wall_times_secs": [ - 0.077365166, - 0.077176125, - 0.076963917 - ], - "max_error": 2.260868995842498e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 146136 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-aci-r14.json b/result/mac-cpu/raw/elementwise_gauss2d-aci-r14.json deleted file mode 100644 index 73f2be4..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-aci-r14.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.019385411432356, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "ref_scale": 0.45540152719045307, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.090454042, - "wall_times_secs": [ - 0.0905545, - 0.090384208, - 0.090454042 - ], - "max_error": 6.0285661724525625e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 56, - 15, - 4 - ], - "n_params": 192784 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-aci-r6.json b/result/mac-cpu/raw/elementwise_gauss2d-aci-r6.json deleted file mode 100644 index 4e5cd51..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-aci-r6.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.2285309222185645, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "ref_scale": 0.5272443812765988, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.001410542, - "wall_times_secs": [ - 0.001627459, - 0.001410542, - 0.0014055 - ], - "max_error": 3.5733924208749677e-11, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 15, - 53, - 16, - 4 - ], - "n_params": 7100 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-aci-r8.json b/result/mac-cpu/raw/elementwise_gauss2d-aci-r8.json deleted file mode 100644 index 7eee165..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-aci-r8.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 0.9572169537165215, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.020037583, - "wall_times_secs": [ - 0.020254792, - 0.020037583, - 0.020003708 - ], - "max_error": 6.13896615746004e-9, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 15, - 57, - 76, - 64, - 16, - 4 - ], - "n_params": 44828 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r10.json b/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r10.json deleted file mode 100644 index 8647f98..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r10.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.168065084, - "wall_times_secs": [ - 1.191107334, - 1.167767542, - 1.168065084 - ], - "max_error": 3.774487979490521e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 59, - 16, - 4 - ], - "n_params": 94308 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r12.json b/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r12.json deleted file mode 100644 index 48f7b6a..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r12.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0168154995876453, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "ref_scale": 0.4568278674896437, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.503801208, - "wall_times_secs": [ - 1.51347925, - 1.503801208, - 1.503380709 - ], - "max_error": 2.4761971891642458e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 79, - 79, - 56, - 16, - 4 - ], - "n_params": 143096 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r14.json b/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r14.json deleted file mode 100644 index 3e87d40..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r14.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.019385411432356, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "ref_scale": 0.45540152719045307, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.610188959, - "wall_times_secs": [ - 1.610188959, - 1.603033875, - 1.625952917 - ], - "max_error": 5.96787041236968e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 79, - 79, - 79, - 69, - 42, - 15, - 4 - ], - "n_params": 182680 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r6.json b/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r6.json deleted file mode 100644 index 6c1e002..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r6.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.2285309222185645, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "ref_scale": 0.5272443812765988, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.044548583, - "wall_times_secs": [ - 0.045958333, - 0.044548583, - 0.043966167 - ], - "max_error": 3.5733924739148716e-11, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 15, - 53, - 16, - 4 - ], - "n_params": 7100 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r8.json b/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r8.json deleted file mode 100644 index b915082..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-fit_treetn-r8.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 0.9572169537165215, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.557197917, - "wall_times_secs": [ - 0.562031458, - 0.557197917, - 0.554985459 - ], - "max_error": 6.0999213141465964e-9, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 15, - 57, - 76, - 64, - 16, - 4 - ], - "n_params": 44828 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-naive-r10.json b/result/mac-cpu/raw/elementwise_gauss2d-naive-r10.json deleted file mode 100644 index 19c205b..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-naive-r10.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 9.077027291, - "wall_times_secs": [ - 9.49257775, - 9.077027291, - 9.066659833 - ], - "max_error": 3.776456191853004e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 96208 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-naive-r12.json b/result/mac-cpu/raw/elementwise_gauss2d-naive-r12.json deleted file mode 100644 index 4900fbc..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-naive-r12.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0168154995876453, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "ref_scale": 0.4568278674896437, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 12.477829375, - "wall_times_secs": [ - 12.313886459, - 12.477829375, - 14.079890166 - ], - "max_error": 2.4767421507421206e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 146136 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-naive-r14.json b/result/mac-cpu/raw/elementwise_gauss2d-naive-r14.json deleted file mode 100644 index c5d465c..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-naive-r14.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.019385411432356, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "ref_scale": 0.45540152719045307, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 12.763546333, - "wall_times_secs": [ - 13.506497458, - 12.763546333, - 12.690097583 - ], - "max_error": 5.962860889458523e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 53, - 16, - 4 - ], - "n_params": 191884 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-naive-r6.json b/result/mac-cpu/raw/elementwise_gauss2d-naive-r6.json deleted file mode 100644 index cdf5475..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-naive-r6.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.2285309222185645, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "ref_scale": 0.5272443812765988, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.0816185, - "wall_times_secs": [ - 0.086886791, - 0.0816185, - 0.074249667 - ], - "max_error": 3.573394620082748e-11, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 15, - 53, - 16, - 4 - ], - "n_params": 7100 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-naive-r8.json b/result/mac-cpu/raw/elementwise_gauss2d-naive-r8.json deleted file mode 100644 index 92cab1a..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-naive-r8.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 0.9572169537165215, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 3.67647025, - "wall_times_secs": [ - 3.67647025, - 3.840164708, - 3.41602725 - ], - "max_error": 6.101614079995761e-9, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 15, - 57, - 76, - 64, - 16, - 4 - ], - "n_params": 44828 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r10.json b/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r10.json deleted file mode 100644 index f432f5b..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r10.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.403529875, - "wall_times_secs": [ - 0.403529875, - 0.402799625, - 0.403822125 - ], - "max_error": 1.0202618431054142, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 16, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 129568 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r12.json b/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r12.json deleted file mode 100644 index 2f25237..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r12.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0168154995876453, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "ref_scale": 0.4568278674896437, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.494615292, - "wall_times_secs": [ - 0.494615292, - 0.493502125, - 0.514279208 - ], - "max_error": 0.12769902013078804, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 16, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 179496 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r14.json b/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r14.json deleted file mode 100644 index 7665b28..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r14.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.019385411432356, - "input_scale_g": 0.8397319458404694, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "ref_scale": 0.45540152719045307, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.497837084, - "wall_times_secs": [ - 0.497923334, - 0.497837084, - 0.497433125 - ], - "max_error": 0.9304330387913473, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 16, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 229424 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r6.json b/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r6.json deleted file mode 100644 index 7f25dd5..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r6.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.2285309222185645, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "ref_scale": 0.5272443812765988, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.020666916, - "wall_times_secs": [ - 0.022381875, - 0.020452791, - 0.020666916 - ], - "max_error": 0.6203611225673633, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 16, - 53, - 53, - 16, - 4 - ], - "n_params": 18356 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r8.json b/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r8.json deleted file mode 100644 index 7825b84..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d-zipup_treetn-r8.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 0.9572169537165215, - "input_scale_g": 0.8724716890024252, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.212005208, - "wall_times_secs": [ - 0.212005208, - 0.211445833, - 0.214132208 - ], - "max_error": 0.6934274876155901, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 16, - 76, - 76, - 76, - 64, - 16, - 4 - ], - "n_params": 74960 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n128.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n128.json deleted file mode 100644 index 16d5827..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n128.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.8485281374238572, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 92552, - "input_path": "norm", - "input_scale_f": 5.532482279799953, - "input_scale_g": 6.147544980719687, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 128, - "r": 8, - "ref_scale": 19.657334849705343, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.076999875, - "wall_times_secs": [ - 0.076999875 - ], - "max_error": 5.78027802345711e-9, - "input_max_bond_dim": 88, - "output_max_bond_dim": 182, - "output_bond_dims": [ - 4, - 16, - 64, - 182, - 58, - 16, - 4 - ], - "n_params": 97168, - "rtol": 1e-8, - "input_build_secs": 0.455598208 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n16.json deleted file mode 100644 index f00f75c..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n16.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.30000000000000004, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 14528, - "input_path": "norm", - "input_scale_f": 3.7382147919908273, - "input_scale_g": 4.48585161337672, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 16, - "r": 6, - "ref_scale": 13.86668062517219, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.003902875, - "wall_times_secs": [ - 0.003902875 - ], - "max_error": 5.2689685431067e-9, - "input_max_bond_dim": 53, - "output_max_bond_dim": 60, - "output_bond_dims": [ - 4, - 16, - 60, - 16, - 4 - ], - "n_params": 8224, - "rtol": 1e-8, - "input_build_secs": 0.024382458 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n256.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n256.json deleted file mode 100644 index 830b38c..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n256.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 1.2000000000000002, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 128460, - "input_path": "norm", - "input_scale_f": 5.886390880387449, - "input_scale_g": 6.480301892112433, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 256, - "r": 8, - "ref_scale": 28.320019452654304, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.09710225, - "wall_times_secs": [ - 0.09710225 - ], - "max_error": 5.565746234905029e-9, - "input_max_bond_dim": 120, - "output_max_bond_dim": 213, - "output_bond_dims": [ - 4, - 16, - 64, - 213, - 63, - 16, - 4 - ], - "n_params": 116876, - "rtol": 1e-8, - "input_build_secs": 0.630147917 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n32.json deleted file mode 100644 index a80b26d..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n32.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.4242640687119286, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 39040, - "input_path": "norm", - "input_scale_f": 6.250287144382089, - "input_scale_g": 5.686702129156313, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 32, - "r": 7, - "ref_scale": 15.782401214047107, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.011871083, - "wall_times_secs": [ - 0.011871083 - ], - "max_error": 6.0893019065270765e-9, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [ - 4, - 16, - 64, - 57, - 16, - 4 - ], - "n_params": 22880, - "rtol": 1e-8, - "input_build_secs": 0.07768775 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n512.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n512.json deleted file mode 100644 index fc86744..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n512.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 1.6970562748477145, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 267264, - "input_path": "norm", - "input_scale_f": 5.90032646628055, - "input_scale_g": 7.17745101842024, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 512, - "r": 9, - "ref_scale": 26.466725829096013, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.386818875, - "wall_times_secs": [ - 0.386818875 - ], - "max_error": 4.435118152582367e-9, - "input_max_bond_dim": 182, - "output_max_bond_dim": 256, - "output_bond_dims": [ - 4, - 16, - 64, - 256, - 192, - 58, - 16, - 4 - ], - "n_params": 315040, - "rtol": 1e-8, - "input_build_secs": 2.7173955 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n64.json deleted file mode 100644 index 3237e8f..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n64.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.6000000000000001, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 43840, - "input_path": "norm", - "input_scale_f": 5.169684368794332, - "input_scale_g": 5.050063587259608, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 64, - "r": 7, - "ref_scale": 20.324044994622827, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.015112459, - "wall_times_secs": [ - 0.015112459 - ], - "max_error": 3.4118570400737463e-9, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [ - 4, - 16, - 64, - 62, - 16, - 4 - ], - "n_params": 24480, - "rtol": 1e-8, - "input_build_secs": 0.086583125 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n8.json deleted file mode 100644 index b36a4c9..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-aci-n8.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.2121320343559643, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 12352, - "input_path": "norm", - "input_scale_f": 3.5922164210268215, - "input_scale_g": 3.825798835109671, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "ref_scale": 5.191380418105756, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.003982958, - "wall_times_secs": [ - 0.003982958 - ], - "max_error": 1.3073282784128505e-8, - "input_max_bond_dim": 45, - "output_max_bond_dim": 54, - "output_bond_dims": [ - 4, - 16, - 54, - 16, - 4 - ], - "n_params": 7456, - "rtol": 1e-8, - "input_build_secs": 0.026983042 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n128.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n128.json deleted file mode 100644 index 2f35b7d..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n128.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.8485281374238572, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 92552, - "input_path": "norm", - "input_scale_f": 5.532482279799953, - "input_scale_g": 6.147544980719687, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 128, - "r": 8, - "ref_scale": 19.657334849705343, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 2.24424225, - "wall_times_secs": [ - 2.24424225 - ], - "max_error": 2.033571571468138e-8, - "input_max_bond_dim": 88, - "output_max_bond_dim": 80, - "output_bond_dims": [ - 4, - 16, - 64, - 80, - 41, - 16, - 4 - ], - "n_params": 40864, - "rtol": 1e-8, - "input_build_secs": 0.455598208 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n16.json deleted file mode 100644 index 77da7a2..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n16.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.30000000000000004, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 14528, - "input_path": "norm", - "input_scale_f": 3.7382147919908273, - "input_scale_g": 4.48585161337672, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 16, - "r": 6, - "ref_scale": 13.86668062517219, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.048296584, - "wall_times_secs": [ - 0.048296584 - ], - "max_error": 1.5169798404183345e-8, - "input_max_bond_dim": 53, - "output_max_bond_dim": 47, - "output_bond_dims": [ - 4, - 16, - 47, - 16, - 4 - ], - "n_params": 6560, - "rtol": 1e-8, - "input_build_secs": 0.024382458 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n256.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n256.json deleted file mode 100644 index da330cb..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n256.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 1.2000000000000002, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 128460, - "input_path": "norm", - "input_scale_f": 5.886390880387449, - "input_scale_g": 6.480301892112433, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 256, - "r": 8, - "ref_scale": 28.320019452654304, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 2.812319541, - "wall_times_secs": [ - 2.812319541 - ], - "max_error": 2.0640479593463016e-8, - "input_max_bond_dim": 120, - "output_max_bond_dim": 108, - "output_bond_dims": [ - 4, - 16, - 64, - 108, - 51, - 16, - 4 - ], - "n_params": 57584, - "rtol": 1e-8, - "input_build_secs": 0.630147917 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n32.json deleted file mode 100644 index 4adaada..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n32.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.4242640687119286, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 39040, - "input_path": "norm", - "input_scale_f": 6.250287144382089, - "input_scale_g": 5.686702129156313, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 32, - "r": 7, - "ref_scale": 15.782401214047107, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.266942375, - "wall_times_secs": [ - 0.266942375 - ], - "max_error": 4.2876464814667403e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 63, - "output_bond_dims": [ - 4, - 16, - 63, - 41, - 16, - 4 - ], - "n_params": 17532, - "rtol": 1e-8, - "input_build_secs": 0.07768775 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n512.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n512.json deleted file mode 100644 index a6b25a0..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n512.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 1.6970562748477145, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 267264, - "input_path": "norm", - "input_scale_f": 5.90032646628055, - "input_scale_g": 7.17745101842024, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 512, - "r": 9, - "ref_scale": 26.466725829096013, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 20.318016375, - "wall_times_secs": [ - 20.318016375 - ], - "max_error": 2.2591923265144526e-8, - "input_max_bond_dim": 182, - "output_max_bond_dim": 169, - "output_bond_dims": [ - 4, - 16, - 64, - 169, - 81, - 41, - 16, - 4 - ], - "n_params": 118568, - "rtol": 1e-8, - "input_build_secs": 2.7173955 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n64.json deleted file mode 100644 index e3e62f7..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n64.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.6000000000000001, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 43840, - "input_path": "norm", - "input_scale_f": 5.169684368794332, - "input_scale_g": 5.050063587259608, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 64, - "r": 7, - "ref_scale": 20.324044994622827, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.285646667, - "wall_times_secs": [ - 0.285646667 - ], - "max_error": 1.1031315057978496e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [ - 4, - 16, - 64, - 51, - 16, - 4 - ], - "n_params": 20960, - "rtol": 1e-8, - "input_build_secs": 0.086583125 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n8.json deleted file mode 100644 index 4f7e22e..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-fit_treetn-n8.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "global", - "box_l": 0.2121320343559643, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_n_params": 12352, - "input_path": "norm", - "input_scale_f": 3.5922164210268215, - "input_scale_g": 3.825798835109671, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "ref_scale": 5.191380418105756, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.041265083, - "wall_times_secs": [ - 0.041265083 - ], - "max_error": 1.4012344756910907e-8, - "input_max_bond_dim": 45, - "output_max_bond_dim": 39, - "output_bond_dims": [ - 4, - 16, - 39, - 16, - 4 - ], - "n_params": 5536, - "rtol": 1e-8, - "input_build_secs": 0.026983042 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n128.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n128.json deleted file mode 100644 index 6897fd0..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n128.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.8485281374238572, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 88, - "input_n_params": 116580, - "input_path": "norm", - "input_scale_f": 5.532482279799953, - "input_scale_g": 6.147544980719687, - "n_error_samples": 128, - "n_gauss": 128, - "n_pairs": 4, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.055791916999999996, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 8, - "ref_scale": 19.657334849705343, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.436984083, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.492826541, - "wall_times_secs": [ - 0.492826541 - ], - "max_error": 4.374461105884408e-8, - "input_max_bond_dim": 59, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 70128, - "n_patches": 4, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 12.414440167 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n16.json deleted file mode 100644 index 2a71d7e..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n16.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.30000000000000004, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 53, - "input_n_params": 11712, - "input_path": "norm", - "input_scale_f": 3.7382147919908273, - "input_scale_g": 4.48585161337672, - "n_error_samples": 128, - "n_gauss": 16, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.003715875, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 6, - "ref_scale": 13.86668062517219, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.012723709, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.016450042, - "wall_times_secs": [ - 0.016450042 - ], - "max_error": 2.9387002456944885e-8, - "input_max_bond_dim": 42, - "output_max_bond_dim": 47, - "output_bond_dims": [], - "n_params": 6560, - "n_patches": 1, - "max_patch_bond": 47, - "rtol": 1e-8, - "input_build_secs": 0.065887875 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n256.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n256.json deleted file mode 100644 index 17578d6..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n256.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 1.2000000000000002, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 120, - "input_n_params": 152000, - "input_path": "norm", - "input_scale_f": 5.886390880387449, - "input_scale_g": 6.480301892112433, - "n_error_samples": 128, - "n_gauss": 256, - "n_pairs": 4, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.047405167, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 8, - "ref_scale": 28.320019452654304, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.441307584, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.488759542, - "wall_times_secs": [ - 0.488759542 - ], - "max_error": 2.8024504443816705e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 82560, - "n_patches": 4, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 29.043728708 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n32.json deleted file mode 100644 index 8e14040..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n32.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.4242640687119286, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 64, - "input_n_params": 29076, - "input_path": "norm", - "input_scale_f": 6.250287144382089, - "input_scale_g": 5.686702129156313, - "n_error_samples": 128, - "n_gauss": 32, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.020222166, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 7, - "ref_scale": 15.782401214047107, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.138504625, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.158742291, - "wall_times_secs": [ - 0.158742291 - ], - "max_error": 4.4726626857324603e-8, - "input_max_bond_dim": 58, - "output_max_bond_dim": 63, - "output_bond_dims": [], - "n_params": 17848, - "n_patches": 1, - "max_patch_bond": 63, - "rtol": 1e-8, - "input_build_secs": 0.303882958 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n512.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n512.json deleted file mode 100644 index 82bb8df..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n512.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 1.6970562748477145, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 182, - "input_n_params": 456956, - "input_path": "norm", - "input_scale_f": 5.90032646628055, - "input_scale_g": 7.17745101842024, - "n_error_samples": 128, - "n_gauss": 512, - "n_pairs": 28, - "n_patches_f": 16, - "n_patches_g": 16, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.34148962099999997, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 9, - "ref_scale": 26.466725829096013, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 1.903011333, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 2.244972208, - "wall_times_secs": [ - 2.244972208 - ], - "max_error": 4.438105297992431e-8, - "input_max_bond_dim": 60, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 294680, - "n_patches": 28, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 197.789211375 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n64.json deleted file mode 100644 index 5ecff2f..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n64.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.6000000000000001, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 64, - "input_n_params": 38080, - "input_path": "norm", - "input_scale_f": 5.169684368794332, - "input_scale_g": 5.050063587259608, - "n_error_samples": 128, - "n_gauss": 64, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.011953334, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 7, - "ref_scale": 20.324044994622827, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.114550208, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.12651925, - "wall_times_secs": [ - 0.12651925 - ], - "max_error": 2.1024712985915138e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 20960, - "n_patches": 1, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 0.40444275 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n8.json deleted file mode 100644 index 7d1e9aa..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_aci-n8.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.2121320343559643, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 45, - "input_n_params": 9488, - "input_path": "norm", - "input_scale_f": 3.5922164210268215, - "input_scale_g": 3.825798835109671, - "n_error_samples": 128, - "n_gauss": 8, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.004921625, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 6, - "ref_scale": 5.191380418105756, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.012552334, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.017480333, - "wall_times_secs": [ - 0.017480333 - ], - "max_error": 4.689575570514132e-8, - "input_max_bond_dim": 34, - "output_max_bond_dim": 39, - "output_bond_dims": [], - "n_params": 5536, - "n_patches": 1, - "max_patch_bond": 39, - "rtol": 1e-8, - "input_build_secs": 0.059774041 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n128.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n128.json deleted file mode 100644 index 92f4e3e..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n128.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.8485281374238572, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 88, - "input_n_params": 116580, - "input_path": "norm", - "input_scale_f": 5.532482279799953, - "input_scale_g": 6.147544980719687, - "n_error_samples": 128, - "n_gauss": 128, - "n_pairs": 4, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.981459375, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 8, - "ref_scale": 19.657334849705343, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.313858166, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.295380959, - "wall_times_secs": [ - 1.295380959 - ], - "max_error": 4.374461295653234e-8, - "input_max_bond_dim": 59, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 70128, - "n_patches": 4, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 12.414440167 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n16.json deleted file mode 100644 index 8b6a018..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n16.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.30000000000000004, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 53, - "input_n_params": 11712, - "input_path": "norm", - "input_scale_f": 3.7382147919908273, - "input_scale_g": 4.48585161337672, - "n_error_samples": 128, - "n_gauss": 16, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.0463405, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 6, - "ref_scale": 13.86668062517219, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.011377167, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.057725917, - "wall_times_secs": [ - 0.057725917 - ], - "max_error": 2.938700040730444e-8, - "input_max_bond_dim": 42, - "output_max_bond_dim": 47, - "output_bond_dims": [], - "n_params": 6560, - "n_patches": 1, - "max_patch_bond": 47, - "rtol": 1e-8, - "input_build_secs": 0.065887875 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n256.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n256.json deleted file mode 100644 index 9ca8f36..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n256.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 1.2000000000000002, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 120, - "input_n_params": 152000, - "input_path": "norm", - "input_scale_f": 5.886390880387449, - "input_scale_g": 6.480301892112433, - "n_error_samples": 128, - "n_gauss": 256, - "n_pairs": 4, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 1.122082291, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 8, - "ref_scale": 28.320019452654304, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.351944875, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.474078792, - "wall_times_secs": [ - 1.474078792 - ], - "max_error": 2.802451096715655e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 82560, - "n_patches": 4, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 29.043728708 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n32.json deleted file mode 100644 index cb6b96e..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n32.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.4242640687119286, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 64, - "input_n_params": 29076, - "input_path": "norm", - "input_scale_f": 6.250287144382089, - "input_scale_g": 5.686702129156313, - "n_error_samples": 128, - "n_gauss": 32, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.219984125, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 7, - "ref_scale": 15.782401214047107, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.084344709, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.304342667, - "wall_times_secs": [ - 0.304342667 - ], - "max_error": 4.472662709298248e-8, - "input_max_bond_dim": 58, - "output_max_bond_dim": 63, - "output_bond_dims": [], - "n_params": 17848, - "n_patches": 1, - "max_patch_bond": 63, - "rtol": 1e-8, - "input_build_secs": 0.303882958 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n512.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n512.json deleted file mode 100644 index 4821f87..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n512.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 1.6970562748477145, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 182, - "input_n_params": 456956, - "input_path": "norm", - "input_scale_f": 5.90032646628055, - "input_scale_g": 7.17745101842024, - "n_error_samples": 128, - "n_gauss": 512, - "n_pairs": 28, - "n_patches_f": 16, - "n_patches_g": 16, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 7.938346001, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 9, - "ref_scale": 26.466725829096013, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 3.242918, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 11.1819605, - "wall_times_secs": [ - 11.1819605 - ], - "max_error": 4.4381047744828957e-8, - "input_max_bond_dim": 60, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 294680, - "n_patches": 28, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 197.789211375 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n64.json deleted file mode 100644 index 075cca9..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n64.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.6000000000000001, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 64, - "input_n_params": 38080, - "input_path": "norm", - "input_scale_f": 5.169684368794332, - "input_scale_g": 5.050063587259608, - "n_error_samples": 128, - "n_gauss": 64, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.280154875, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 7, - "ref_scale": 20.324044994622827, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.093518708, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.373686958, - "wall_times_secs": [ - 0.373686958 - ], - "max_error": 2.1024711937094293e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 20960, - "n_patches": 1, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 0.40444275 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n8.json deleted file mode 100644 index 3b42d35..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_fit_treetn-n8.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.2121320343559643, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 45, - "input_n_params": 9488, - "input_path": "norm", - "input_scale_f": 3.5922164210268215, - "input_scale_g": 3.825798835109671, - "n_error_samples": 128, - "n_gauss": 8, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.039554791, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 6, - "ref_scale": 5.191380418105756, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.009961959, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.049524833, - "wall_times_secs": [ - 0.049524833 - ], - "max_error": 4.6895761693191156e-8, - "input_max_bond_dim": 34, - "output_max_bond_dim": 39, - "output_bond_dims": [], - "n_params": 5536, - "n_patches": 1, - "max_patch_bond": 39, - "rtol": 1e-8, - "input_build_secs": 0.059774041 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n128.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n128.json deleted file mode 100644 index 0ce26c1..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n128.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.8485281374238572, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 88, - "input_n_params": 116580, - "input_path": "norm", - "input_scale_f": 5.532482279799953, - "input_scale_g": 6.147544980719687, - "n_error_samples": 128, - "n_gauss": 128, - "n_pairs": 4, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 1.568745583, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 8, - "ref_scale": 19.657334849705343, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.311206459, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.880009166, - "wall_times_secs": [ - 1.880009166 - ], - "max_error": 4.374461620971222e-8, - "input_max_bond_dim": 59, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 70128, - "n_patches": 4, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 12.414440167 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n16.json deleted file mode 100644 index 15298b9..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n16.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.30000000000000004, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 53, - "input_n_params": 11712, - "input_path": "norm", - "input_scale_f": 3.7382147919908273, - "input_scale_g": 4.48585161337672, - "n_error_samples": 128, - "n_gauss": 16, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.068071125, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 6, - "ref_scale": 13.86668062517219, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.011422542, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.079504, - "wall_times_secs": [ - 0.079504 - ], - "max_error": 2.9386984778796058e-8, - "input_max_bond_dim": 42, - "output_max_bond_dim": 47, - "output_bond_dims": [], - "n_params": 6560, - "n_patches": 1, - "max_patch_bond": 47, - "rtol": 1e-8, - "input_build_secs": 0.065887875 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n256.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n256.json deleted file mode 100644 index c2f87b8..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n256.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 1.2000000000000002, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 120, - "input_n_params": 152000, - "input_path": "norm", - "input_scale_f": 5.886390880387449, - "input_scale_g": 6.480301892112433, - "n_error_samples": 128, - "n_gauss": 256, - "n_pairs": 4, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 12.936895166, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 8, - "ref_scale": 28.320019452654304, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.353398625, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 13.290350459, - "wall_times_secs": [ - 13.290350459 - ], - "max_error": 2.802451774139408e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 82560, - "n_patches": 4, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 29.043728708 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n32.json deleted file mode 100644 index 07f5841..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n32.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.4242640687119286, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 64, - "input_n_params": 29076, - "input_path": "norm", - "input_scale_f": 6.250287144382089, - "input_scale_g": 5.686702129156313, - "n_error_samples": 128, - "n_gauss": 32, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.416250625, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 7, - "ref_scale": 15.782401214047107, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.084256458, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.5005235, - "wall_times_secs": [ - 0.5005235 - ], - "max_error": 4.472662637369837e-8, - "input_max_bond_dim": 58, - "output_max_bond_dim": 63, - "output_bond_dims": [], - "n_params": 17848, - "n_patches": 1, - "max_patch_bond": 63, - "rtol": 1e-8, - "input_build_secs": 0.303882958 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n512.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n512.json deleted file mode 100644 index 2e01a29..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n512.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 1.6970562748477145, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 182, - "input_n_params": 456956, - "input_path": "norm", - "input_scale_f": 5.90032646628055, - "input_scale_g": 7.17745101842024, - "n_error_samples": 128, - "n_gauss": 512, - "n_pairs": 28, - "n_patches_f": 16, - "n_patches_g": 16, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 16.321064210999996, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 9, - "ref_scale": 26.466725829096013, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 1.455904084, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 17.777521791, - "wall_times_secs": [ - 17.777521791 - ], - "max_error": 4.438105405379002e-8, - "input_max_bond_dim": 60, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 294680, - "n_patches": 28, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 197.789211375 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n64.json deleted file mode 100644 index 4615d26..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n64.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.6000000000000001, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 64, - "input_n_params": 38080, - "input_path": "norm", - "input_scale_f": 5.169684368794332, - "input_scale_g": 5.050063587259608, - "n_error_samples": 128, - "n_gauss": 64, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 3.19426125, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 7, - "ref_scale": 20.324044994622827, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.098098208, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 3.292373833, - "wall_times_secs": [ - 3.292373833 - ], - "max_error": 2.1024710800871708e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 64, - "output_bond_dims": [], - "n_params": 20960, - "n_patches": 1, - "max_patch_bond": 64, - "rtol": 1e-8, - "input_build_secs": 0.40444275 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n8.json deleted file mode 100644 index eb61e24..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-aniso-patched_naive-n8.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "aniso_rho_max": 8.0, - "aniso_sigma_minor": 0.05, - "aniso_spacing_widths": 3.0, - "arm_kind": "patched", - "box_l": 0.2121320343559643, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "aniso", - "fit_nsweeps": 2, - "input_global_chi": 45, - "input_n_params": 9488, - "input_path": "norm", - "input_scale_f": 3.5922164210268215, - "input_scale_g": 3.825798835109671, - "n_error_samples": 128, - "n_gauss": 8, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.045515625, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 6, - "ref_scale": 5.191380418105756, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.00985575, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.055378833, - "wall_times_secs": [ - 0.055378833 - ], - "max_error": 4.6895771958419456e-8, - "input_max_bond_dim": 34, - "output_max_bond_dim": 39, - "output_bond_dims": [], - "n_params": 5536, - "n_patches": 1, - "max_patch_bond": 39, - "rtol": 1e-8, - "input_build_secs": 0.059774041 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n16.json deleted file mode 100644 index 8a017e1..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n16.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 8.485281374238571, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 165304, - "input_path": "norm", - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.607736541, - "wall_times_secs": [ - 0.607736541 - ], - "max_error": 4.539652927303982e-9, - "input_max_bond_dim": 103, - "output_max_bond_dim": 95, - "output_bond_dims": [ - 4, - 14, - 37, - 95, - 95, - 60, - 36, - 25, - 14, - 4 - ], - "n_params": 89152, - "rtol": 1e-8, - "input_build_secs": 2.097030709 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n32.json deleted file mode 100644 index eeb6cb3..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n32.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 12.0, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 222852, - "input_path": "norm", - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.0490555, - "wall_times_secs": [ - 1.0490555 - ], - "max_error": 9.342919314700749e-9, - "input_max_bond_dim": 117, - "output_max_bond_dim": 129, - "output_bond_dims": [ - 4, - 15, - 36, - 103, - 129, - 90, - 48, - 27, - 15, - 4 - ], - "n_params": 141176, - "rtol": 1e-8, - "input_build_secs": 2.848328708 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n64.json deleted file mode 100644 index 7b50241..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n64.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 16.970562748477143, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 325416, - "input_path": "norm", - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 2.050237708, - "wall_times_secs": [ - 2.050237708 - ], - "max_error": 6.229325214569724e-9, - "input_max_bond_dim": 143, - "output_max_bond_dim": 183, - "output_bond_dims": [ - 4, - 15, - 34, - 102, - 183, - 146, - 94, - 59, - 29, - 15, - 4 - ], - "n_params": 283624, - "rtol": 1e-8, - "input_build_secs": 5.760831917 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n8.json deleted file mode 100644 index 7b248fd..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-aci-n8.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 6.0, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 102324, - "input_path": "norm", - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.061002333, - "wall_times_secs": [ - 0.061002333 - ], - "max_error": 8.848670872161537e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 15, - 42, - 76, - 62, - 45, - 26, - 15, - 4 - ], - "n_params": 52048, - "rtol": 1e-8, - "input_build_secs": 1.012199458 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n16.json deleted file mode 100644 index 1c68108..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n16.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 8.485281374238571, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 165304, - "input_path": "norm", - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 25.353480584, - "wall_times_secs": [ - 25.353480584 - ], - "max_error": 1.8971647978169645e-8, - "input_max_bond_dim": 103, - "output_max_bond_dim": 80, - "output_bond_dims": [ - 4, - 14, - 34, - 80, - 63, - 40, - 26, - 19, - 13, - 4 - ], - "n_params": 50612, - "rtol": 1e-8, - "input_build_secs": 2.097030709 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n32.json deleted file mode 100644 index 0b3cc05..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n32.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 12.0, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 222852, - "input_path": "norm", - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 31.466695208, - "wall_times_secs": [ - 31.466695208 - ], - "max_error": 3.519872128622014e-8, - "input_max_bond_dim": 117, - "output_max_bond_dim": 95, - "output_bond_dims": [ - 4, - 14, - 33, - 95, - 85, - 51, - 32, - 21, - 13, - 4 - ], - "n_params": 74800, - "rtol": 1e-8, - "input_build_secs": 2.848328708 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n64.json deleted file mode 100644 index 39c0191..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n64.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 16.970562748477143, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 325416, - "input_path": "norm", - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 48.28244475, - "wall_times_secs": [ - 48.28244475 - ], - "max_error": 1.5037407504788906e-8, - "input_max_bond_dim": 143, - "output_max_bond_dim": 120, - "output_bond_dims": [ - 4, - 14, - 33, - 95, - 120, - 70, - 43, - 28, - 19, - 13, - 4 - ], - "n_params": 114024, - "rtol": 1e-8, - "input_build_secs": 5.760831917 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n8.json deleted file mode 100644 index 6230c31..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-fit_treetn-n8.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "global", - "box_l": 6.0, - "contract_max_bond": 512, - "contract_tol": 1e-8, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_n_params": 102324, - "input_path": "norm", - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 1, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 19.306642833, - "wall_times_secs": [ - 19.306642833 - ], - "max_error": 1.1172010208057941e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 15, - 41, - 61, - 47, - 34, - 21, - 13, - 4 - ], - "n_params": 34752, - "rtol": 1e-8, - "input_build_secs": 1.012199458 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n16.json deleted file mode 100644 index f4b82d6..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n16.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 8.485281374238571, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 103, - "input_n_params": 163644, - "input_path": "norm", - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "n_pairs": 16, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.6650735010000001, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 6.401296458, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 7.066553417, - "wall_times_secs": [ - 7.066553417 - ], - "max_error": 1.580350543208069e-8, - "input_max_bond_dim": 52, - "output_max_bond_dim": 58, - "output_bond_dims": [], - "n_params": 106972, - "n_patches": 14, - "max_patch_bond": 58, - "rtol": 1e-8, - "input_build_secs": 26.197543541 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n32.json deleted file mode 100644 index aa849b8..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n32.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 12.0, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 117, - "input_n_params": 234952, - "input_path": "norm", - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "n_pairs": 6, - "n_patches_f": 6, - "n_patches_g": 7, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 1.3890829580000001, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 22.306666875, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 23.695854917, - "wall_times_secs": [ - 23.695854917 - ], - "max_error": 3.6299889890812615e-8, - "input_max_bond_dim": 62, - "output_max_bond_dim": 67, - "output_bond_dims": [], - "n_params": 128876, - "n_patches": 6, - "max_patch_bond": 67, - "rtol": 1e-8, - "input_build_secs": 58.801807792 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n64.json deleted file mode 100644 index 30c0ebe..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n64.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 16.970562748477143, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 143, - "input_n_params": 432932, - "input_path": "norm", - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "n_pairs": 64, - "n_patches_f": 13, - "n_patches_g": 16, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 2.54408533, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 33.209824959, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 35.75466275, - "wall_times_secs": [ - 35.75466275 - ], - "max_error": 4.085870378476233e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 60, - "output_bond_dims": [], - "n_params": 381004, - "n_patches": 33, - "max_patch_bond": 60, - "rtol": 1e-8, - "input_build_secs": 151.587226583 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n8.json deleted file mode 100644 index 4bd8b77..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_aci-n8.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_aci", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 6.0, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 79, - "input_n_params": 67368, - "input_path": "norm", - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 0.461384375, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 4.286869209, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 4.748277, - "wall_times_secs": [ - 4.748277 - ], - "max_error": 3.791958069579959e-8, - "input_max_bond_dim": 63, - "output_max_bond_dim": 63, - "output_bond_dims": [], - "n_params": 35952, - "n_patches": 1, - "max_patch_bond": 63, - "rtol": 1e-8, - "input_build_secs": 1.8528791249999998 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n16.json deleted file mode 100644 index 4425a29..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n16.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 8.485281374238571, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 103, - "input_n_params": 163644, - "input_path": "norm", - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "n_pairs": 16, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 17.530709835, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 1.830697959, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 19.361653833, - "wall_times_secs": [ - 19.361653833 - ], - "max_error": 1.5803955517235203e-8, - "input_max_bond_dim": 52, - "output_max_bond_dim": 58, - "output_bond_dims": [], - "n_params": 106972, - "n_patches": 14, - "max_patch_bond": 58, - "rtol": 1e-8, - "input_build_secs": 26.197543541 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n32.json deleted file mode 100644 index df94d1f..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n32.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 12.0, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 117, - "input_n_params": 234952, - "input_path": "norm", - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "n_pairs": 6, - "n_patches_f": 6, - "n_patches_g": 7, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 6.529577374999999, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 3.171790666, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 9.701471, - "wall_times_secs": [ - 9.701471 - ], - "max_error": 3.629177749454661e-8, - "input_max_bond_dim": 62, - "output_max_bond_dim": 67, - "output_bond_dims": [], - "n_params": 128876, - "n_patches": 6, - "max_patch_bond": 67, - "rtol": 1e-8, - "input_build_secs": 58.801807792 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n64.json deleted file mode 100644 index d173dc0..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n64.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 16.970562748477143, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 143, - "input_n_params": 432932, - "input_path": "norm", - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "n_pairs": 64, - "n_patches_f": 13, - "n_patches_g": 16, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 47.016373253000005, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 6.61332075, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 53.630615167, - "wall_times_secs": [ - 53.630615167 - ], - "max_error": 3.7520060350379335e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 60, - "output_bond_dims": [], - "n_params": 380632, - "n_patches": 33, - "max_patch_bond": 60, - "rtol": 1e-8, - "input_build_secs": 151.587226583 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n8.json deleted file mode 100644 index f85fa61..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_fit_treetn-n8.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_fit_treetn", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 6.0, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 79, - "input_n_params": 67368, - "input_path": "norm", - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 4.280207, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 1.2366953330000001, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 5.516941375, - "wall_times_secs": [ - 5.516941375 - ], - "max_error": 3.7902203501397e-8, - "input_max_bond_dim": 63, - "output_max_bond_dim": 63, - "output_bond_dims": [], - "n_params": 35952, - "n_patches": 1, - "max_patch_bond": 63, - "rtol": 1e-8, - "input_build_secs": 1.8528791249999998 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n16.json deleted file mode 100644 index 18b2195..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n16.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 8.485281374238571, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 103, - "input_n_params": 163644, - "input_path": "norm", - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "n_pairs": 16, - "n_patches_f": 4, - "n_patches_g": 4, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 9.964956418000002, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 1.879537375, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 11.844710583, - "wall_times_secs": [ - 11.844710583 - ], - "max_error": 1.580398551161485e-8, - "input_max_bond_dim": 52, - "output_max_bond_dim": 58, - "output_bond_dims": [], - "n_params": 106972, - "n_patches": 14, - "max_patch_bond": 58, - "rtol": 1e-8, - "input_build_secs": 26.197543541 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n32.json deleted file mode 100644 index 6da03ba..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n32.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 12.0, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 117, - "input_n_params": 234952, - "input_path": "norm", - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "n_pairs": 6, - "n_patches_f": 6, - "n_patches_g": 7, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 9.999381542, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 3.191985167, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 13.191468833, - "wall_times_secs": [ - 13.191468833 - ], - "max_error": 3.629194254858184e-8, - "input_max_bond_dim": 62, - "output_max_bond_dim": 67, - "output_bond_dims": [], - "n_params": 128876, - "n_patches": 6, - "max_patch_bond": 67, - "rtol": 1e-8, - "input_build_secs": 58.801807792 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n64.json deleted file mode 100644 index 5ea2055..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n64.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 16.970562748477143, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 143, - "input_n_params": 432932, - "input_path": "norm", - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "n_pairs": 64, - "n_patches_f": 13, - "n_patches_g": 16, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 24.510428582, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 38.552345334, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 63.063681125, - "wall_times_secs": [ - 63.063681125 - ], - "max_error": 3.75200722414877e-8, - "input_max_bond_dim": 64, - "output_max_bond_dim": 60, - "output_bond_dims": [], - "n_params": 380632, - "n_patches": 33, - "max_patch_bond": 60, - "rtol": 1e-8, - "input_build_secs": 151.587226583 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n8.json deleted file mode 100644 index 94285e4..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_patched-smooth-patched_naive-n8.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_patched", - "algorithm": "patched_naive", - "params": { - "aci_tolerance": "absolute", - "alpha_range": [ - 0.5, - 8.0 - ], - "arm_kind": "patched", - "box_l": 6.0, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "family": "smooth", - "fit_nsweeps": 2, - "input_global_chi": 79, - "input_n_params": 67368, - "input_path": "norm", - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "n_pairs": 1, - "n_patches_f": 1, - "n_patches_g": 1, - "output_bond_dims_note": "patched output, see n_params and n_patches", - "pairs_secs": 5.627966541, - "patch_max_bond": 64, - "patch_max_iter": 20, - "product_max_bond": 4096, - "product_tol": 1e-10, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 1, - "split_strategy": "gain", - "truncate_secs": 0.866296125, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 6.494283666, - "wall_times_secs": [ - 6.494283666 - ], - "max_error": 3.7902316620498875e-8, - "input_max_bond_dim": 63, - "output_max_bond_dim": 63, - "output_bond_dims": [], - "n_params": 35952, - "n_patches": 1, - "max_patch_bond": 63, - "rtol": 1e-8, - "input_build_secs": 1.8528791249999998 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n16.json deleted file mode 100644 index eb4fdb3..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n16.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 8.485281374238571, - "contract_max_bond": 102, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.1155555, - "wall_times_secs": [ - 0.1155555, - 0.115350292, - 0.116715875 - ], - "max_error": 4.5364339523007866e-9, - "input_max_bond_dim": 102, - "output_max_bond_dim": 102, - "output_bond_dims": [ - 4, - 15, - 50, - 102, - 102, - 102, - 102, - 64, - 16, - 4 - ], - "n_params": 178984 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n32.json deleted file mode 100644 index 77c71f4..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n32.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 12.0, - "contract_max_bond": 117, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.166075625, - "wall_times_secs": [ - 0.166290625, - 0.165802709, - 0.166075625 - ], - "max_error": 5.7685251667230114e-9, - "input_max_bond_dim": 117, - "output_max_bond_dim": 117, - "output_bond_dims": [ - 4, - 15, - 47, - 117, - 117, - 117, - 117, - 64, - 16, - 4 - ], - "n_params": 223660 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n64.json deleted file mode 100644 index 364dbad..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n64.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 16.970562748477143, - "contract_max_bond": 139, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.314027083, - "wall_times_secs": [ - 0.325243875, - 0.314027083, - 0.312599333 - ], - "max_error": 9.338148589494676e-9, - "input_max_bond_dim": 139, - "output_max_bond_dim": 139, - "output_bond_dims": [ - 4, - 16, - 36, - 125, - 139, - 139, - 139, - 139, - 64, - 16, - 4 - ], - "n_params": 361880 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n8.json deleted file mode 100644 index a5d5af7..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-aci-n8.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "aci", - "params": { - "aci_scale_tolerance": true, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.052878959, - "wall_times_secs": [ - 0.053412167, - 0.052874625, - 0.052878959 - ], - "max_error": 6.223251050241363e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 96208 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n16.json deleted file mode 100644 index 578be4f..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n16.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 8.485281374238571, - "contract_max_bond": 102, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 2.892961333, - "wall_times_secs": [ - 2.892961333, - 2.878866625, - 2.8931801249999998 - ], - "max_error": 4.5364337808362785e-9, - "input_max_bond_dim": 102, - "output_max_bond_dim": 102, - "output_bond_dims": [ - 4, - 15, - 50, - 102, - 102, - 102, - 102, - 61, - 16, - 4 - ], - "n_params": 177568 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n32.json deleted file mode 100644 index 88f6652..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n32.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 12.0, - "contract_max_bond": 117, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 4.714800875, - "wall_times_secs": [ - 4.8765835840000005, - 4.714270459, - 4.714800875 - ], - "max_error": 4.66800177735083e-9, - "input_max_bond_dim": 117, - "output_max_bond_dim": 117, - "output_bond_dims": [ - 4, - 15, - 44, - 117, - 117, - 117, - 117, - 58, - 16, - 4 - ], - "n_params": 218884 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n64.json deleted file mode 100644 index 0281c27..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n64.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 16.970562748477143, - "contract_max_bond": 139, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 9.52576875, - "wall_times_secs": [ - 9.52576875, - 9.511702167, - 9.737572792 - ], - "max_error": 3.6933263700119017e-9, - "input_max_bond_dim": 139, - "output_max_bond_dim": 139, - "output_bond_dims": [ - 4, - 16, - 36, - 121, - 139, - 139, - 139, - 139, - 62, - 16, - 4 - ], - "n_params": 357840 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n8.json deleted file mode 100644 index 6a9ac53..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-fit_treetn-n8.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "fit_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.1942243750000001, - "wall_times_secs": [ - 1.202320458, - 1.189706667, - 1.1942243750000001 - ], - "max_error": 6.508758217452865e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 15, - 57, - 79, - 79, - 79, - 59, - 16, - 4 - ], - "n_params": 94308 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n16.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n16.json deleted file mode 100644 index 8dc3fad..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n16.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 8.485281374238571, - "contract_max_bond": 102, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 2.066477285160887, - "input_scale_g": 0.7767228331725128, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 16, - "r": 11, - "r0": 10, - "ref_scale": 0.6551543244294972, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.978557583, - "wall_times_secs": [ - 0.995294667, - 0.978557583, - 0.974623417 - ], - "max_error": 0.47494985629062736, - "input_max_bond_dim": 102, - "output_max_bond_dim": 102, - "output_bond_dims": [ - 16, - 102, - 102, - 102, - 102, - 102, - 102, - 64, - 16, - 4 - ], - "n_params": 245152 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n32.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n32.json deleted file mode 100644 index 8cceebb..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n32.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 12.0, - "contract_max_bond": 117, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 2.052318887509088, - "input_scale_g": 1.1152448818838097, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 32, - "r": 11, - "r0": 10, - "ref_scale": 0.5531115445990792, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.645472834, - "wall_times_secs": [ - 1.69949525, - 1.640519917, - 1.645472834 - ], - "max_error": 0.3877915155734421, - "input_max_bond_dim": 117, - "output_max_bond_dim": 117, - "output_bond_dims": [ - 16, - 117, - 117, - 117, - 117, - 117, - 117, - 64, - 16, - 4 - ], - "n_params": 315652 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n64.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n64.json deleted file mode 100644 index 9e3c585..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n64.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 16.970562748477143, - "contract_max_bond": 139, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.3958326041780285, - "input_scale_g": 2.224869772066804, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 64, - "r": 12, - "r0": 10, - "ref_scale": 1.232428758864407, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 3.297927375, - "wall_times_secs": [ - 3.306983708, - 3.297927375, - 3.283535084 - ], - "max_error": 0.3579166992941887, - "input_max_bond_dim": 139, - "output_max_bond_dim": 139, - "output_bond_dims": [ - 16, - 139, - 139, - 139, - 139, - 139, - 139, - 139, - 64, - 16, - 4 - ], - "n_params": 512616 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n8.json b/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n8.json deleted file mode 100644 index 3614996..0000000 --- a/result/mac-cpu/raw/elementwise_gauss2d_scaling-zipup_treetn-n8.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d_scaling", - "algorithm": "zipup_treetn", - "params": { - "aci_scale_tolerance": false, - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "input_scale_f": 1.0116257087218627, - "input_scale_g": 0.8457799985689375, - "l0": 6.0, - "max_bond": 512, - "n0": 8, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "r0": 10, - "ref_scale": 0.46251481110172116, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.401894041, - "wall_times_secs": [ - 0.409204958, - 0.401894041, - 0.400624625 - ], - "max_error": 0.43369445348441826, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 16, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 129568 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r10.json b/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r10.json deleted file mode 100644 index 49f8bf7..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r10.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.923248292, - "wall_times_secs": [ - 0.934483375, - 0.9215675, - 0.923248292 - ], - "max_error": 4.169143482960435e-9, - "input_max_bond_dim": 78, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 63, - 78, - 78, - 78, - 47, - 16, - 4 - ], - "n_params": 90576 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r12.json b/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r12.json deleted file mode 100644 index 66f8ee6..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r12.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.118955958, - "wall_times_secs": [ - 1.148642458, - 1.118365125, - 1.118955958 - ], - "max_error": 3.1993700217125625e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 63, - 79, - 79, - 79, - 79, - 67, - 37, - 15, - 4 - ], - "n_params": 132668 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r14.json b/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r14.json deleted file mode 100644 index 48b211c..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r14.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 81, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.295280459, - "wall_times_secs": [ - 1.295280459, - 1.311744166, - 1.269217375 - ], - "max_error": 2.9896874401496837e-9, - "input_max_bond_dim": 81, - "output_max_bond_dim": 81, - "output_bond_dims": [ - 4, - 16, - 63, - 81, - 81, - 81, - 81, - 81, - 56, - 38, - 28, - 13, - 4 - ], - "n_params": 162284 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r6.json b/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r6.json deleted file mode 100644 index f9231d1..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r6.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.035627709, - "wall_times_secs": [ - 0.037691583, - 0.035550292, - 0.035627709 - ], - "max_error": 5.678887293713753e-10, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 16, - 53, - 16, - 4 - ], - "n_params": 7328 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r8.json b/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r8.json deleted file mode 100644 index 9141ae8..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-fit_treetn-r8.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.505469875, - "wall_times_secs": [ - 0.515169459, - 0.505469875, - 0.504405 - ], - "max_error": 2.34924530146701e-9, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 16, - 63, - 76, - 63, - 16, - 4 - ], - "n_params": 46912 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r10.json b/result/mac-cpu/raw/mpo_mpo_quantics-naive-r10.json deleted file mode 100644 index 8c4b73a..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r10.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 46.324204583, - "wall_times_secs": [ - 46.865150625, - 46.324204583, - 46.137870292 - ], - "max_error": 4.169933236683973e-9, - "input_max_bond_dim": 78, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 63, - 78, - 78, - 78, - 64, - 16, - 4 - ], - "n_params": 96968 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r12.json b/result/mac-cpu/raw/mpo_mpo_quantics-naive-r12.json deleted file mode 100644 index abfac8e..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r12.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 132.115506333, - "wall_times_secs": [ - 132.115506333, - 131.858142792, - 132.608052417 - ], - "max_error": 3.1970154160923157e-9, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 63, - 79, - 79, - 79, - 79, - 79, - 64, - 16, - 4 - ], - "n_params": 148660 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r14.json b/result/mac-cpu/raw/mpo_mpo_quantics-naive-r14.json deleted file mode 100644 index 133f431..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r14.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 81, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 150.476919333, - "wall_times_secs": [ - 150.476919333, - 150.699118292, - 150.310839084 - ], - "max_error": 2.9812521532847897e-9, - "input_max_bond_dim": 81, - "output_max_bond_dim": 81, - "output_bond_dims": [ - 4, - 16, - 63, - 81, - 81, - 81, - 81, - 81, - 81, - 77, - 44, - 16, - 4 - ], - "n_params": 197524 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r6.json b/result/mac-cpu/raw/mpo_mpo_quantics-naive-r6.json deleted file mode 100644 index 57c3be5..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r6.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.028089292, - "wall_times_secs": [ - 0.036693583, - 0.027322084, - 0.028089292 - ], - "max_error": 5.678887690966114e-10, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 16, - 53, - 16, - 4 - ], - "n_params": 7328 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r8.json b/result/mac-cpu/raw/mpo_mpo_quantics-naive-r8.json deleted file mode 100644 index dc078e1..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-naive-r8.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.674386417, - "wall_times_secs": [ - 1.971600541, - 1.674386417, - 1.6653805830000001 - ], - "max_error": 2.3492331904032465e-9, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 16, - 63, - 76, - 64, - 16, - 4 - ], - "n_params": 47280 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r10.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r10.json deleted file mode 100644 index 6e99bcf..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r10.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.289377833, - "wall_times_secs": [ - 0.31557, - 0.289377833, - 0.288015125 - ], - "max_error": 0.00003553152699658155, - "input_max_bond_dim": 78, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 78, - 78, - 78, - 78, - 16 - ], - "n_params": 126736 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r12.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r12.json deleted file mode 100644 index 54844d3..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r12.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.322734125, - "wall_times_secs": [ - 0.324746541, - 0.321577625, - 0.322734125 - ], - "max_error": 0.00002060892406987671, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 64, - 79, - 79, - 79, - 79, - 79, - 79, - 62, - 16 - ], - "n_params": 173036 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r14.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r14.json deleted file mode 100644 index cee4b74..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r14.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 81, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.351298083, - "wall_times_secs": [ - 0.357557417, - 0.351298083, - 0.3512745 - ], - "max_error": 0.00001563352386048191, - "input_max_bond_dim": 81, - "output_max_bond_dim": 81, - "output_bond_dims": [ - 4, - 16, - 64, - 81, - 81, - 81, - 81, - 81, - 81, - 78, - 52, - 42, - 15 - ], - "n_params": 209136 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r6.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r6.json deleted file mode 100644 index 7e8f826..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r6.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.013474792, - "wall_times_secs": [ - 0.014115917, - 0.013474792, - 0.0133275 - ], - "max_error": 0.00010539578698940664, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 16, - 53, - 53, - 16 - ], - "n_params": 18356 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r8.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r8.json deleted file mode 100644 index 4a0377a..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_simplett-r8.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.186066375, - "wall_times_secs": [ - 0.187024875, - 0.185806541, - 0.186066375 - ], - "max_error": 0.00002269979852158187, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 16, - 64, - 76, - 76, - 76, - 16 - ], - "n_params": 74960 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r10.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r10.json deleted file mode 100644 index cc1dd89..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r10.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.324415791, - "wall_times_secs": [ - 0.324415791, - 0.323590917, - 0.325711834 - ], - "max_error": 0.00003553152699672512, - "input_max_bond_dim": 78, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 4, - 16, - 64, - 78, - 78, - 78, - 78, - 78, - 16 - ], - "n_params": 126736 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r12.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r12.json deleted file mode 100644 index 1906a6c..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r12.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.374230583, - "wall_times_secs": [ - 0.380719834, - 0.374230583, - 0.368341833 - ], - "max_error": 0.000020608924069917183, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 64, - 79, - 79, - 79, - 79, - 79, - 79, - 62, - 16 - ], - "n_params": 173036 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r14.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r14.json deleted file mode 100644 index 54ceaaa..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r14.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 81, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.401662083, - "wall_times_secs": [ - 0.401662083, - 0.403976833, - 0.3993765 - ], - "max_error": 0.000015633523860462873, - "input_max_bond_dim": 81, - "output_max_bond_dim": 81, - "output_bond_dims": [ - 4, - 16, - 64, - 81, - 81, - 81, - 81, - 81, - 81, - 78, - 52, - 42, - 15 - ], - "n_params": 209136 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r6.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r6.json deleted file mode 100644 index 1e98201..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r6.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.019677833, - "wall_times_secs": [ - 0.020472916, - 0.019677833, - 0.0193685 - ], - "max_error": 0.00010539578698969932, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 16, - 53, - 53, - 16 - ], - "n_params": 18356 -} \ No newline at end of file diff --git a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r8.json b/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r8.json deleted file mode 100644 index 9555abc..0000000 --- a/result/mac-cpu/raw/mpo_mpo_quantics-zipup_treetn-r8.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "contract_tol": 1e-15, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.210269625, - "wall_times_secs": [ - 0.209796333, - 0.210269625, - 0.210326917 - ], - "max_error": 0.00002269979852154305, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 16, - 64, - 76, - 76, - 76, - 16 - ], - "n_params": 74960 -} \ No newline at end of file diff --git a/result/mac-cpu/run.yaml b/result/mac-cpu/run.yaml deleted file mode 100644 index 0f2bf99..0000000 --- a/result/mac-cpu/run.yaml +++ /dev/null @@ -1,9 +0,0 @@ -profile: mac-cpu -date: 2026-08-14T09:05:48Z -machine: mac-cpu -os: Darwin arm64 -chip: Apple M5 Max -memory_gb: 128 -repo_rev: 92102f8b504e03f943f7d1799509c9674c7a1ade -tensor4all_rs_rev: c9ecb7f0d4eec4bbf6db51dc7648a4b2d84b4f34 -threads: 1 diff --git a/result/mac-m1-8gb/elementwise_fourier-error.svg b/result/mac-m1-8gb/elementwise_fourier-error.svg deleted file mode 100644 index f2119d1..0000000 --- a/result/mac-m1-8gb/elementwise_fourier-error.svg +++ /dev/null @@ -1,1199 +0,0 @@ - - - - - - - - 2026-08-07T15:17:19.777638 - image/svg+xml - - - Matplotlib v3.11.0, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-m1-8gb/elementwise_fourier-time.svg b/result/mac-m1-8gb/elementwise_fourier-time.svg deleted file mode 100644 index d267d92..0000000 --- a/result/mac-m1-8gb/elementwise_fourier-time.svg +++ /dev/null @@ -1,1486 +0,0 @@ - - - - - - - - 2026-08-07T15:17:19.727821 - image/svg+xml - - - Matplotlib v3.11.0, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-m1-8gb/elementwise_fourier.md b/result/mac-m1-8gb/elementwise_fourier.md deleted file mode 100644 index 95ef760..0000000 --- a/result/mac-m1-8gb/elementwise_fourier.md +++ /dev/null @@ -1,12 +0,0 @@ -# elementwise_fourier - -| algorithm | points | fitted time exponent | worst max abs error | -|---|---|---|---| -| aci | 6 | 0.93 | 3.74e-07 | -| fit | 6 | 1.03 | 6.49e-07 | -| naive | 6 | 1.52 | 6.49e-07 | -| zipup | 6 | 1.71 | 3.90e-06 | - -![time](./elementwise_fourier-time.svg) - -![error](./elementwise_fourier-error.svg) diff --git a/result/mac-m1-8gb/elementwise_gauss2d-error.svg b/result/mac-m1-8gb/elementwise_gauss2d-error.svg deleted file mode 100644 index df7ab40..0000000 --- a/result/mac-m1-8gb/elementwise_gauss2d-error.svg +++ /dev/null @@ -1,1168 +0,0 @@ - - - - - - - - 2026-08-07T15:17:19.969520 - image/svg+xml - - - Matplotlib v3.11.0, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-m1-8gb/elementwise_gauss2d-time.svg b/result/mac-m1-8gb/elementwise_gauss2d-time.svg deleted file mode 100644 index 2eb10b8..0000000 --- a/result/mac-m1-8gb/elementwise_gauss2d-time.svg +++ /dev/null @@ -1,1665 +0,0 @@ - - - - - - - - 2026-08-07T15:17:19.907060 - image/svg+xml - - - Matplotlib v3.11.0, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-m1-8gb/elementwise_gauss2d.md b/result/mac-m1-8gb/elementwise_gauss2d.md deleted file mode 100644 index 8d4b1b1..0000000 --- a/result/mac-m1-8gb/elementwise_gauss2d.md +++ /dev/null @@ -1,14 +0,0 @@ -# elementwise_gauss2d - -| algorithm | points | fitted time exponent | worst max relative error | -|---|---|---|---| -| aci | 5 | 8.08 | 1.28e-08 | -| fit_treetn | 5 | 7.26 | 6.40e-08 | -| naive | 5 | 11.23 | 6.39e-08 | -| zipup_treetn | 5 | 6.90 | 6.20e-01 | - -Note: every algorithm forms the product at the same output budget, its maximum bond dimension capped at the input rank chi, so the error column is the discriminator. The exact elementwise product has rank up to chi squared, so this budget is tight: naive, fit_treetn and aci stay near the working tolerance while zipup_treetn spends the whole budget and still returns an order-unity relative error. Raising the budget recovers it, so that is the price of the fixed budget rather than a broken arm. There is no simplett arm here: simplett exposes no elementwise product for tensor trains at the pinned revision, so this case cannot compare the two engines on one algorithm the way case 2 does. The engine that ran each arm is recorded as engine: local for naive, treetn for the two hadamard arms, aci for the cross interpolation. The fitted time exponent is measured against input chi along a sweep of r, where the site count also grows, so it is not a pure chi power law. - -![time](./elementwise_gauss2d-time.svg) - -![error](./elementwise_gauss2d-error.svg) diff --git a/result/mac-m1-8gb/mpo_mpo_quantics-error.svg b/result/mac-m1-8gb/mpo_mpo_quantics-error.svg deleted file mode 100644 index a9de5ad..0000000 --- a/result/mac-m1-8gb/mpo_mpo_quantics-error.svg +++ /dev/null @@ -1,1596 +0,0 @@ - - - - - - - - 2026-08-07T15:17:20.200210 - image/svg+xml - - - Matplotlib v3.11.0, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-m1-8gb/mpo_mpo_quantics-time.svg b/result/mac-m1-8gb/mpo_mpo_quantics-time.svg deleted file mode 100644 index 3eb6987..0000000 --- a/result/mac-m1-8gb/mpo_mpo_quantics-time.svg +++ /dev/null @@ -1,1618 +0,0 @@ - - - - - - - - 2026-08-07T15:17:20.132668 - image/svg+xml - - - Matplotlib v3.11.0, https://matplotlib.org/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/result/mac-m1-8gb/mpo_mpo_quantics.md b/result/mac-m1-8gb/mpo_mpo_quantics.md deleted file mode 100644 index 37d4d75..0000000 --- a/result/mac-m1-8gb/mpo_mpo_quantics.md +++ /dev/null @@ -1,14 +0,0 @@ -# mpo_mpo_quantics - -| algorithm | points | fitted time exponent | worst max relative error | -|---|---|---|---| -| fit_treetn | 5 | 6.15 | 2.95e-08 | -| naive | 5 | 16.10 | 2.89e-08 | -| zipup_simplett | 5 | 6.89 | 1.05e-04 | -| zipup_treetn | 5 | 6.16 | 1.05e-04 | - -Note: every algorithm contracts at the same output budget, its maximum bond dimension capped at the input rank chi, so the error column is the discriminator. naive and zipup_simplett run on the simplett engine, zipup_treetn and fit_treetn on treetn; both engines truncate relative to the largest singular value at the pinned revision. The two zipup arms are the same algorithm on the two engines, so their difference isolates the engine, and it is now confined to wall time. The fitted time exponent is measured against input chi along a sweep of r, where the site count also grows, so it is not a pure chi power law. - -![time](./mpo_mpo_quantics-time.svg) - -![error](./mpo_mpo_quantics-error.svg) diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k128.json b/result/mac-m1-8gb/raw/elementwise_fourier-aci-k128.json deleted file mode 100644 index 7b30045..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k128.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "aci", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 128, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.002217333, - "wall_times_secs": [ - 0.002217333, - 0.002189625, - 0.002474917, - 0.002509459, - 0.002181209 - ], - "max_error": 3.73953913510689e-7, - "input_max_bond_dim": 16, - "output_max_bond_dim": 32, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 32, - 32, - 23, - 17, - 14, - 10, - 8, - 6, - 6, - 4, - 4, - 4, - 4, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k16.json b/result/mac-m1-8gb/raw/elementwise_fourier-aci-k16.json deleted file mode 100644 index 3b386a5..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k16.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "aci", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 16, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.000918458, - "wall_times_secs": [ - 0.000918458, - 0.000909417, - 0.0009015, - 0.001276167, - 0.000965209 - ], - "max_error": 8.81700849861402e-8, - "input_max_bond_dim": 8, - "output_max_bond_dim": 16, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 14, - 12, - 9, - 8, - 6, - 6, - 4, - 4, - 4, - 4, - 4, - 3, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k32.json b/result/mac-m1-8gb/raw/elementwise_fourier-aci-k32.json deleted file mode 100644 index 1cf045a..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k32.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "aci", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 32, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.001123166, - "wall_times_secs": [ - 0.001123166, - 0.001143875, - 0.001123167, - 0.0010935, - 0.001119333 - ], - "max_error": 1.1721608824323926e-7, - "input_max_bond_dim": 11, - "output_max_bond_dim": 22, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 22, - 17, - 12, - 10, - 9, - 7, - 7, - 5, - 5, - 5, - 4, - 4, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k4.json b/result/mac-m1-8gb/raw/elementwise_fourier-aci-k4.json deleted file mode 100644 index c96ca67..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k4.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "aci", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 4, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.000690417, - "wall_times_secs": [ - 0.000686833, - 0.000689125, - 0.000690417, - 0.000698083, - 0.000697 - ], - "max_error": 5.065903399571004e-8, - "input_max_bond_dim": 5, - "output_max_bond_dim": 9, - "output_bond_dims": [ - 2, - 4, - 8, - 9, - 9, - 8, - 6, - 6, - 4, - 4, - 3, - 3, - 3, - 3, - 3, - 3, - 2, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k64.json b/result/mac-m1-8gb/raw/elementwise_fourier-aci-k64.json deleted file mode 100644 index 721ca7d..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k64.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "aci", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 64, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.001463083, - "wall_times_secs": [ - 0.0014465, - 0.001479167, - 0.001467833, - 0.001463083, - 0.001462083 - ], - "max_error": 2.859549581072562e-7, - "input_max_bond_dim": 14, - "output_max_bond_dim": 28, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 28, - 22, - 17, - 13, - 10, - 9, - 7, - 7, - 5, - 5, - 5, - 5, - 4, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k8.json b/result/mac-m1-8gb/raw/elementwise_fourier-aci-k8.json deleted file mode 100644 index 692f083..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-aci-k8.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "aci", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 8, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.000839959, - "wall_times_secs": [ - 0.000838125, - 0.000898625, - 0.000871125, - 0.000839959, - 0.000832334 - ], - "max_error": 6.328716341074523e-8, - "input_max_bond_dim": 8, - "output_max_bond_dim": 16, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 12, - 10, - 8, - 7, - 7, - 5, - 5, - 5, - 4, - 4, - 3, - 3, - 3, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k64.json b/result/mac-m1-8gb/raw/elementwise_fourier-fit-k64.json deleted file mode 100644 index 7889a9e..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-fit-k64.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "fit", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 64, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.053355459, - "wall_times_secs": [ - 0.053355459, - 0.053971375, - 0.051933667, - 0.05134975, - 0.053771709 - ], - "max_error": 6.49112503618478e-7, - "input_max_bond_dim": 14, - "output_max_bond_dim": 16, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 13, - 10, - 8, - 7, - 6, - 5, - 4, - 4, - 4, - 3, - 3, - 3, - 3, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k128.json b/result/mac-m1-8gb/raw/elementwise_fourier-naive-k128.json deleted file mode 100644 index f096b29..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k128.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "naive", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 128, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.011822416, - "wall_times_secs": [ - 0.012348375, - 0.011829833, - 0.01140425, - 0.011822416, - 0.011665167 - ], - "max_error": 5.744880204194558e-7, - "input_max_bond_dim": 16, - "output_max_bond_dim": 18, - "output_bond_dims": [ - 2, - 4, - 8, - 16, - 18, - 13, - 10, - 8, - 7, - 6, - 5, - 4, - 4, - 4, - 3, - 3, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k16.json b/result/mac-m1-8gb/raw/elementwise_fourier-naive-k16.json deleted file mode 100644 index 4ad9e67..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k16.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "naive", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 16, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.002389791, - "wall_times_secs": [ - 0.003750125, - 0.002239709, - 0.005330292, - 0.002064667, - 0.002389791 - ], - "max_error": 2.5142270964435527e-7, - "input_max_bond_dim": 8, - "output_max_bond_dim": 10, - "output_bond_dims": [ - 2, - 4, - 8, - 10, - 8, - 7, - 6, - 5, - 5, - 4, - 4, - 3, - 3, - 3, - 3, - 2, - 2, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k32.json b/result/mac-m1-8gb/raw/elementwise_fourier-naive-k32.json deleted file mode 100644 index 31c51b1..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k32.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "naive", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 32, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.004399959, - "wall_times_secs": [ - 0.004410458, - 0.004660792, - 0.004399959, - 0.003861417, - 0.003613459 - ], - "max_error": 6.377530752244781e-7, - "input_max_bond_dim": 11, - "output_max_bond_dim": 13, - "output_bond_dims": [ - 2, - 4, - 8, - 13, - 10, - 8, - 7, - 6, - 5, - 5, - 4, - 4, - 3, - 3, - 3, - 3, - 2, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k4.json b/result/mac-m1-8gb/raw/elementwise_fourier-naive-k4.json deleted file mode 100644 index 04d567c..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k4.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "naive", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 4, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.002248333, - "wall_times_secs": [ - 0.000883917, - 0.000874458, - 0.002248333, - 0.002482958, - 0.00266575 - ], - "max_error": 7.932838114995547e-8, - "input_max_bond_dim": 5, - "output_max_bond_dim": 8, - "output_bond_dims": [ - 2, - 4, - 8, - 7, - 6, - 5, - 5, - 4, - 4, - 3, - 3, - 3, - 3, - 3, - 2, - 2, - 2, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k8.json b/result/mac-m1-8gb/raw/elementwise_fourier-naive-k8.json deleted file mode 100644 index 5e67124..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-naive-k8.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "naive", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 8, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.001547459, - "wall_times_secs": [ - 0.001968291, - 0.001545125, - 0.001547459, - 0.001585542, - 0.001542916 - ], - "max_error": 7.423232997232557e-8, - "input_max_bond_dim": 8, - "output_max_bond_dim": 8, - "output_bond_dims": [ - 2, - 4, - 8, - 8, - 7, - 6, - 5, - 5, - 4, - 4, - 3, - 3, - 3, - 3, - 3, - 2, - 2, - 2, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k128.json b/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k128.json deleted file mode 100644 index 1ba22e0..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k128.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 128, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.041826084, - "wall_times_secs": [ - 0.04223375, - 0.041826084, - 0.041552375, - 0.042678375, - 0.040479583 - ], - "max_error": 3.8975117842573395e-6, - "input_max_bond_dim": 16, - "output_max_bond_dim": 106, - "output_bond_dims": [ - 4, - 16, - 47, - 106, - 105, - 79, - 58, - 38, - 28, - 21, - 19, - 12, - 12, - 7, - 6, - 5, - 5, - 4, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k16.json b/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k16.json deleted file mode 100644 index aa44464..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k16.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 16, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.008960416, - "wall_times_secs": [ - 0.008928875, - 0.008751708, - 0.00958575, - 0.009063083, - 0.008960416 - ], - "max_error": 1.6779439436850145e-7, - "input_max_bond_dim": 8, - "output_max_bond_dim": 52, - "output_bond_dims": [ - 4, - 16, - 50, - 52, - 42, - 30, - 22, - 20, - 13, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k32.json b/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k32.json deleted file mode 100644 index 276c56e..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k32.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 32, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.015414042, - "wall_times_secs": [ - 0.015939333, - 0.014718292, - 0.014638792, - 0.015414042, - 0.016207416 - ], - "max_error": 1.2766629300444693e-7, - "input_max_bond_dim": 11, - "output_max_bond_dim": 80, - "output_bond_dims": [ - 4, - 16, - 36, - 80, - 59, - 38, - 29, - 22, - 22, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k4.json b/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k4.json deleted file mode 100644 index e95f128..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k4.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 4, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.005509959, - "wall_times_secs": [ - 0.006814042, - 0.005432125, - 0.005458084, - 0.005509959, - 0.005615792 - ], - "max_error": 5.139049197194527e-8, - "input_max_bond_dim": 5, - "output_max_bond_dim": 22, - "output_bond_dims": [ - 4, - 13, - 19, - 21, - 22, - 22, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 3, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k64.json b/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k64.json deleted file mode 100644 index 511e9c6..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k64.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 64, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.02202175, - "wall_times_secs": [ - 0.022430958, - 0.021770417, - 0.02202175, - 0.0217315, - 0.023495916 - ], - "max_error": 5.017750121476428e-7, - "input_max_bond_dim": 14, - "output_max_bond_dim": 104, - "output_bond_dims": [ - 4, - 16, - 33, - 104, - 80, - 58, - 38, - 30, - 21, - 20, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k8.json b/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k8.json deleted file mode 100644 index 27e51d1..0000000 --- a/result/mac-m1-8gb/raw/elementwise_fourier-zipup-k8.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_fourier", - "algorithm": "zipup", - "params": { - "error_metric": "max_abs", - "error_seed": 999, - "fit_nfullsweeps": 2, - "k_max": 8, - "max_bond": 4096, - "n_error_samples": 256, - "r": 20, - "runs": 5, - "warmups": 1 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.006852583, - "wall_times_secs": [ - 0.007326042, - 0.006977208, - 0.006852583, - 0.006825375, - 0.006586 - ], - "max_error": 9.541251568258087e-8, - "input_max_bond_dim": 8, - "output_max_bond_dim": 52, - "output_bond_dims": [ - 4, - 15, - 52, - 42, - 31, - 23, - 22, - 15, - 13, - 8, - 8, - 8, - 8, - 6, - 3, - 3, - 3, - 3, - 2 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r10.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r10.json deleted file mode 100644 index c489c3d..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.04045425, - "wall_times_secs": [ - 0.041787208, - 0.04045425, - 0.040000417 - ], - "max_error": 8.72532007250987e-9, - "input_max_bond_dim": 78, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 15, - 42, - 76, - 62, - 44, - 28, - 15, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r12.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r12.json deleted file mode 100644 index 5b40b37..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 80, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.045901833, - "wall_times_secs": [ - 0.046244166, - 0.045192333, - 0.045901833 - ], - "max_error": 1.1160684309644163e-8, - "input_max_bond_dim": 80, - "output_max_bond_dim": 75, - "output_bond_dims": [ - 4, - 15, - 42, - 75, - 63, - 46, - 29, - 21, - 15, - 10, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r14.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r14.json deleted file mode 100644 index fe2b276..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.045774417, - "wall_times_secs": [ - 0.047346958, - 0.045774417, - 0.044783834 - ], - "max_error": 1.2770188053699731e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 15, - 42, - 76, - 62, - 46, - 30, - 21, - 16, - 12, - 10, - 8, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r6.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r6.json deleted file mode 100644 index 7f30f91..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.001545417, - "wall_times_secs": [ - 0.001881041, - 0.001545417, - 0.00152875 - ], - "max_error": 3.5733924208573965e-11, - "input_max_bond_dim": 53, - "output_max_bond_dim": 42, - "output_bond_dims": [ - 4, - 15, - 42, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r8.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r8.json deleted file mode 100644 index 36d957b..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-aci-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "aci", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "aci", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.015126917, - "wall_times_secs": [ - 0.016227083, - 0.015126917, - 0.014629708 - ], - "max_error": 1.2497590315313835e-8, - "input_max_bond_dim": 76, - "output_max_bond_dim": 71, - "output_bond_dims": [ - 4, - 15, - 42, - 71, - 50, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r10.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r10.json deleted file mode 100644 index cb9df78..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.972767, - "wall_times_secs": [ - 0.972767, - 0.994268209, - 0.958598334 - ], - "max_error": 1.9836531258887958e-8, - "input_max_bond_dim": 78, - "output_max_bond_dim": 62, - "output_bond_dims": [ - 4, - 15, - 41, - 62, - 47, - 34, - 21, - 13, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r12.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r12.json deleted file mode 100644 index b58a341..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 80, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.178024542, - "wall_times_secs": [ - 1.189688166, - 1.178024542, - 1.107682875 - ], - "max_error": 1.3803705222386574e-8, - "input_max_bond_dim": 80, - "output_max_bond_dim": 62, - "output_bond_dims": [ - 4, - 15, - 41, - 62, - 48, - 34, - 21, - 15, - 13, - 10, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r14.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r14.json deleted file mode 100644 index ebc74cb..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.154263209, - "wall_times_secs": [ - 1.157109417, - 1.154263209, - 1.119221209 - ], - "max_error": 6.397715006695308e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 15, - 41, - 61, - 48, - 34, - 21, - 15, - 13, - 10, - 9, - 6, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r6.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r6.json deleted file mode 100644 index 0dbbb1a..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.05706875, - "wall_times_secs": [ - 0.058173375, - 0.05706875, - 0.054887125 - ], - "max_error": 8.469584914590248e-9, - "input_max_bond_dim": 53, - "output_max_bond_dim": 39, - "output_bond_dims": [ - 4, - 15, - 39, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r8.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r8.json deleted file mode 100644 index f80f8aa..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-fit_treetn-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.56175725, - "wall_times_secs": [ - 0.568093166, - 0.56175725, - 0.538907708 - ], - "max_error": 2.2915795640544333e-8, - "input_max_bond_dim": 76, - "output_max_bond_dim": 60, - "output_bond_dims": [ - 4, - 15, - 41, - 60, - 42, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r10.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r10.json deleted file mode 100644 index 27880d7..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 7.5827165, - "wall_times_secs": [ - 7.5827165, - 7.420138542, - 7.909769958 - ], - "max_error": 1.9976261374435312e-8, - "input_max_bond_dim": 78, - "output_max_bond_dim": 62, - "output_bond_dims": [ - 4, - 15, - 41, - 62, - 47, - 34, - 21, - 13, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r12.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r12.json deleted file mode 100644 index 907544e..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 80, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 8.44051175, - "wall_times_secs": [ - 8.633888583, - 8.44051175, - 8.303600417 - ], - "max_error": 1.3745654399347714e-8, - "input_max_bond_dim": 80, - "output_max_bond_dim": 62, - "output_bond_dims": [ - 4, - 15, - 41, - 62, - 48, - 34, - 21, - 15, - 13, - 10, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r14.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r14.json deleted file mode 100644 index 55f33cc..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 8.108915, - "wall_times_secs": [ - 8.108915, - 8.016968791, - 8.8515625 - ], - "max_error": 6.392037127239305e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 15, - 41, - 61, - 48, - 34, - 21, - 15, - 13, - 10, - 9, - 6, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r6.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r6.json deleted file mode 100644 index 7a43f79..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.08726675, - "wall_times_secs": [ - 0.101217208, - 0.08726675, - 0.086296167 - ], - "max_error": 8.469584907906082e-9, - "input_max_bond_dim": 53, - "output_max_bond_dim": 39, - "output_bond_dims": [ - 4, - 15, - 39, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r8.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r8.json deleted file mode 100644 index 8a01e3e..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-naive-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "local", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 4.199380083, - "wall_times_secs": [ - 4.199380083, - 4.187815333, - 4.209877417 - ], - "max_error": 2.2915804773040776e-8, - "input_max_bond_dim": 76, - "output_max_bond_dim": 60, - "output_bond_dims": [ - 4, - 15, - 41, - 60, - 42, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r10.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r10.json deleted file mode 100644 index b530100..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 78, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.317696, - "wall_times_secs": [ - 0.320329208, - 0.317696, - 0.315762708 - ], - "max_error": 0.21142057459008276, - "input_max_bond_dim": 78, - "output_max_bond_dim": 78, - "output_bond_dims": [ - 15, - 78, - 78, - 78, - 78, - 78, - 64, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r12.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r12.json deleted file mode 100644 index 2ff848c..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 80, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.417353667, - "wall_times_secs": [ - 0.423708334, - 0.417353667, - 0.40901 - ], - "max_error": 0.5416692034232038, - "input_max_bond_dim": 80, - "output_max_bond_dim": 80, - "output_bond_dims": [ - 15, - 80, - 80, - 80, - 80, - 80, - 80, - 80, - 64, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r14.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r14.json deleted file mode 100644 index c91b1dd..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.401304166, - "wall_times_secs": [ - 0.404765292, - 0.401304166, - 0.391784583 - ], - "max_error": 0.5878371696840221, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 15, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 79, - 63, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r6.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r6.json deleted file mode 100644 index 3a9b789..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.022220291, - "wall_times_secs": [ - 0.024070834, - 0.021266167, - 0.022220291 - ], - "max_error": 0.6202737571371212, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 15, - 53, - 53, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r8.json b/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r8.json deleted file mode 100644 index dc4f2f0..0000000 --- a/result/mac-m1-8gb/raw/elementwise_gauss2d-zipup_treetn-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "elementwise_gauss2d", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 2, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.172837375, - "wall_times_secs": [ - 0.189060625, - 0.172837375, - 0.172629875 - ], - "max_error": 0.16724117363954089, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 15, - 76, - 76, - 76, - 64, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r10.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r10.json deleted file mode 100644 index b59e291..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.492274125, - "wall_times_secs": [ - 0.4932655, - 0.492274125, - 0.479605792 - ], - "max_error": 2.9539855624266096e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 60, - "output_bond_dims": [ - 4, - 16, - 50, - 60, - 37, - 27, - 16, - 13, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r12.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r12.json deleted file mode 100644 index e1382e5..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 77, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.500031625, - "wall_times_secs": [ - 0.504006083, - 0.500031625, - 0.499653084 - ], - "max_error": 2.070892038241914e-8, - "input_max_bond_dim": 77, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 16, - 50, - 61, - 37, - 28, - 19, - 15, - 10, - 10, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r14.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r14.json deleted file mode 100644 index 0a5a1c6..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.528855709, - "wall_times_secs": [ - 0.528855709, - 0.52914775, - 0.517535083 - ], - "max_error": 2.1852073835543292e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 16, - 50, - 61, - 37, - 28, - 20, - 15, - 10, - 10, - 6, - 6, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r6.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r6.json deleted file mode 100644 index b031ab5..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.042907625, - "wall_times_secs": [ - 0.042907625, - 0.041362458, - 0.04309525 - ], - "max_error": 8.635113584926432e-9, - "input_max_bond_dim": 53, - "output_max_bond_dim": 48, - "output_bond_dims": [ - 4, - 16, - 48, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r8.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r8.json deleted file mode 100644 index 7ba50af..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-fit_treetn-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "fit_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.30234675, - "wall_times_secs": [ - 0.300435667, - 0.30234675, - 0.303897208 - ], - "max_error": 1.7132805237699633e-8, - "input_max_bond_dim": 76, - "output_max_bond_dim": 59, - "output_bond_dims": [ - 4, - 16, - 50, - 59, - 35, - 15, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r10.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r10.json deleted file mode 100644 index a659131..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 15.87572, - "wall_times_secs": [ - 19.126222083, - 15.58784575, - 15.87572 - ], - "max_error": 2.8907148724288823e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 16, - 50, - 61, - 37, - 27, - 16, - 13, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r12.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r12.json deleted file mode 100644 index eb19955..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 77, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 45.131875625, - "wall_times_secs": [ - 45.131875625, - 45.027893666, - 47.278726125 - ], - "max_error": 2.0708309827528808e-8, - "input_max_bond_dim": 77, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 16, - 50, - 61, - 37, - 28, - 19, - 15, - 10, - 10, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r14.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r14.json deleted file mode 100644 index 67d9aee..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 47.881931416, - "wall_times_secs": [ - 47.881931416, - 49.479438541, - 46.728464792 - ], - "max_error": 2.185578943114592e-8, - "input_max_bond_dim": 79, - "output_max_bond_dim": 61, - "output_bond_dims": [ - 4, - 16, - 50, - 61, - 37, - 28, - 20, - 15, - 10, - 10, - 6, - 6, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r6.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r6.json deleted file mode 100644 index 99f50c3..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.035191459, - "wall_times_secs": [ - 0.040577959, - 0.035191459, - 0.033102875 - ], - "max_error": 8.635113688761741e-9, - "input_max_bond_dim": 53, - "output_max_bond_dim": 48, - "output_bond_dims": [ - 4, - 16, - 48, - 16, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r8.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r8.json deleted file mode 100644 index 26cc810..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-naive-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "naive", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 1.251666375, - "wall_times_secs": [ - 1.782366583, - 1.251666375, - 1.231603292 - ], - "max_error": 1.714210385626156e-8, - "input_max_bond_dim": 76, - "output_max_bond_dim": 59, - "output_bond_dims": [ - 4, - 16, - 50, - 59, - 35, - 15, - 4 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r10.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r10.json deleted file mode 100644 index 03e79ca..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.215443625, - "wall_times_secs": [ - 0.220902333, - 0.214023333, - 0.215443625 - ], - "max_error": 0.000018324862761517898, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 55, - 79, - 79, - 78, - 45, - 30, - 11 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r12.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r12.json deleted file mode 100644 index 589aafc..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 77, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.22005775, - "wall_times_secs": [ - 0.234810125, - 0.219585917, - 0.22005775 - ], - "max_error": 0.00003511182473688767, - "input_max_bond_dim": 77, - "output_max_bond_dim": 77, - "output_bond_dims": [ - 4, - 16, - 55, - 77, - 77, - 77, - 51, - 35, - 20, - 19, - 8 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r14.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r14.json deleted file mode 100644 index 6692d2b..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.229025292, - "wall_times_secs": [ - 0.252914291, - 0.229025292, - 0.2278385 - ], - "max_error": 0.000023561742363498955, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 55, - 79, - 79, - 79, - 51, - 35, - 20, - 19, - 10, - 10, - 8 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r6.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r6.json deleted file mode 100644 index d7cc281..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.014192875, - "wall_times_secs": [ - 0.015053084, - 0.014192875, - 0.013402833 - ], - "max_error": 0.00010539578698944702, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 16, - 53, - 53, - 16 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r8.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r8.json deleted file mode 100644 index a781ef5..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_simplett-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_simplett", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "simplett", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.136467792, - "wall_times_secs": [ - 0.148038583, - 0.136467792, - 0.121870916 - ], - "max_error": 0.000019587549800793103, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 16, - 55, - 76, - 76, - 55, - 12 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r10.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r10.json deleted file mode 100644 index b99c679..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r10.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 10, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.251113042, - "wall_times_secs": [ - 0.253925292, - 0.24596, - 0.251113042 - ], - "max_error": 0.00001832486276147961, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 55, - 79, - 79, - 78, - 45, - 30, - 11 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r12.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r12.json deleted file mode 100644 index 3184ba0..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r12.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 77, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 12, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.249906667, - "wall_times_secs": [ - 0.256157625, - 0.249906667, - 0.248593125 - ], - "max_error": 0.0000351118247367353, - "input_max_bond_dim": 77, - "output_max_bond_dim": 77, - "output_bond_dims": [ - 4, - 16, - 55, - 77, - 77, - 77, - 51, - 35, - 20, - 19, - 8 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r14.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r14.json deleted file mode 100644 index 153eadf..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r14.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 79, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 14, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.272822916, - "wall_times_secs": [ - 0.278212917, - 0.272822916, - 0.261364209 - ], - "max_error": 0.000023561742363509665, - "input_max_bond_dim": 79, - "output_max_bond_dim": 79, - "output_bond_dims": [ - 4, - 16, - 55, - 79, - 79, - 79, - 51, - 35, - 20, - 19, - 10, - 10, - 8 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r6.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r6.json deleted file mode 100644 index 1f5b026..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r6.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 53, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 6, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.021768791, - "wall_times_secs": [ - 0.021768791, - 0.0226725, - 0.021391792 - ], - "max_error": 0.00010539578698937637, - "input_max_bond_dim": 53, - "output_max_bond_dim": 53, - "output_bond_dims": [ - 4, - 16, - 53, - 53, - 16 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r8.json b/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r8.json deleted file mode 100644 index 0ee229f..0000000 --- a/result/mac-m1-8gb/raw/mpo_mpo_quantics-zipup_treetn-r8.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "algorithm": "zipup_treetn", - "params": { - "alpha_range": [ - 0.5, - 8.0 - ], - "box_l": 6.0, - "contract_max_bond": 76, - "engine": "treetn", - "error_metric": "max_rel_vs_analytic", - "error_seed": 99, - "fit_nsweeps": 1, - "max_bond": 512, - "n_error_samples": 128, - "n_gauss": 8, - "r": 8, - "runs": 3, - "warmups": 0 - }, - "seed": 0, - "tolerance": 1e-8, - "wall_time_median_secs": 0.153142875, - "wall_times_secs": [ - 0.153142875, - 0.146932417, - 0.15360075 - ], - "max_error": 0.000019587549800404928, - "input_max_bond_dim": 76, - "output_max_bond_dim": 76, - "output_bond_dims": [ - 4, - 16, - 55, - 76, - 76, - 55, - 12 - ] -} \ No newline at end of file diff --git a/result/mac-m1-8gb/run.yaml b/result/mac-m1-8gb/run.yaml deleted file mode 100644 index 9405f7f..0000000 --- a/result/mac-m1-8gb/run.yaml +++ /dev/null @@ -1,9 +0,0 @@ -profile: mac-m1-8gb -date: 2026-08-07T13:17:18Z -machine: mac-m1-8gb -os: Darwin arm64 -chip: Apple M1 -memory_gb: 8 -repo_rev: 266ff4c1d6757de046b592566c9bea62a0f2685a -tensor4all_rs_rev: ae655a9ec08a0c3df8c25369b84be0d04e2a2bf3 -threads: default diff --git a/scripts/report.py b/scripts/report.py old mode 100644 new mode 100755 index 5c60339..30ff8e4 --- a/scripts/report.py +++ b/scripts/report.py @@ -1,462 +1,94 @@ #!/usr/bin/env python3 -"""Render Markdown reports and SVG scaling plots from RunRecord JSON files. +"""Render and validate the three maintained benchmark cases.""" -Usage: uv run scripts/report.py result/ -""" import json import sys -from collections import defaultdict +from collections import Counter, defaultdict from pathlib import Path -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import numpy as np - -X_AXIS = { - # case name -> (record field used as x, axis label). A field name prefixed - # with "params." is read out of the record's params object instead of the top - # level, which is where a case whose knob is not a bond dimension keeps it. - "elementwise_fourier": ("input_max_bond_dim", "input bond dimension chi"), - "mpo_mpo_quantics": ("input_max_bond_dim", "input bond dimension chi"), - "elementwise_gauss2d": ("input_max_bond_dim", "input bond dimension chi"), - "elementwise_gauss2d_scaling": ("input_max_bond_dim", "input bond dimension chi"), - "elementwise_gauss2d_patched": ("params.n_gauss", "number of Gaussians N"), -} - -X_SYMBOL = { - # case name -> short symbol of the x axis, used in the fitted exponent - # labels. Every case sweeps a bond dimension except case 5, which sweeps N. - "elementwise_gauss2d_patched": "N", -} - -# Case 6 has an intentionally hand-maintained crossover table because its x -# points are selected by input TCI caps and every committed run records a failed -# accuracy gate. Do not replace that context with the generic scaling report. -HAND_MAINTAINED_CASES = {"mpo_mpo_aniso_patched"} - -ERROR_LABEL = { - # case name -> what `max_error` in the records actually measures - "elementwise_fourier": "max abs error", - "mpo_mpo_quantics": "max relative error", - "elementwise_gauss2d": "max relative error", - "elementwise_gauss2d_scaling": "max relative error", - "elementwise_gauss2d_patched": "max relative error", +EXPECTED = { + "elementwise_fourier": {"naive", "zipup", "fit", "aci"}, + "gaussian_elementwise": {"global_fit", "patched_fit", "global_aci", "patched_aci"}, + "gaussian_mpo_contraction": {"global_fit", "patched_fit"}, } -NOTES = { - # case name -> caveat emitted under the summary table - "mpo_mpo_quantics": ( - "Note: every algorithm contracts at the same output budget, its " - "maximum bond dimension capped at the input rank chi, and the cap is " - "the only truncation control: the contraction tolerance is pinned " - "inert at contract_tol, so every arm spends the whole budget unless " - "its exact rank is smaller and the error " - "column is the discriminator. naive and zipup_simplett run on the " - "simplett engine, zipup_treetn and fit_treetn on treetn; both engines " - "truncate relative to the largest singular value at the pinned " - "revision. The two zipup arms are the same algorithm on the two " - "engines, so their difference isolates the engine, and it is now " - "confined to wall time. " - "The fitted time exponent is measured against input chi " - "along a sweep of r, where the site count also grows, so it is not " - "a pure chi power law." - ), - "elementwise_gauss2d": ( - "Note: every algorithm forms the product at the same output budget, " - "its maximum bond dimension capped at the input rank chi, and the cap " - "is the only truncation control: the product tolerance is pinned inert " - "at contract_tol and the aci arm runs with a scale-relative stopping " - "criterion, so every arm spends the whole budget unless its exact rank " - "is smaller and the error " - "column is the discriminator. The exact elementwise product has rank up " - "to chi squared, so this budget is tight: naive, fit_treetn and aci " - "stay near the working tolerance while zipup_treetn spends the whole " - "budget and still returns an order-unity relative error. Raising the " - "budget recovers it, so that is the price of the fixed budget rather " - "than a broken arm. There is no simplett arm here: simplett exposes no " - "elementwise product for tensor trains at the pinned revision, so this " - "case cannot compare the two engines on one algorithm the way case 2 " - "does. The engine that ran each arm is recorded as engine: local for " - "naive, treetn for the two hadamard arms, aci for the cross " - "interpolation. " - "The fitted time exponent is measured against input chi along a sweep " - "of r, where the site count also grows, so it is not a pure chi power " - "law." - ), - "elementwise_gauss2d_scaling": ( - "Note: this case is the density-constant scaling study of " - "elementwise_gauss2d. The number of Gaussians N is swept while the box " - "area grows proportionally to N, box half-width L = L0 sqrt(N / N0), so " - "the Gaussians per unit area stay fixed, and the bit count grows with " - "the box, R = R0 + round(log2(L / L0)), so the grid spacing and hence " - "the resolution per Gaussian stay roughly constant. The quantity of " - "interest is the input rank chi_in as a function of N, reported in the " - "instance table and the chi plot below. The elementwise product itself " - "runs at the same fixed output budget chi_out <= chi_in as case 3, " - "decided by the cap alone with an inert contract_tol. The " - "naive arm of case 3 is excluded here: it forms the full chi_in-squared " - "bond before truncating, which dominates the sweep at these ranks " - "without adding a conclusion, since it tracks fit_treetn to the last " - "reported digit in case 3. As in case 3, zipup_treetn spends the whole " - "budget and still returns an order-unity relative error. " - "The fitted time exponent is measured against input chi along a sweep " - "of N, where the site count also grows, so it is not a pure chi power " - "law." - ), - "elementwise_gauss2d_patched": ( - "Note: this case runs two instance families, recorded per arm as family " - "and tabulated separately below, and it is controlled by the accuracy " - "instead of by a fixed output budget. The default family aniso is N " - "anisotropic narrow spikes at a fixed spacing-to-width ratio, whose random " - "orientations and aspect ratios push the global rank toward the geometric " - "bound of the bit count; smooth is the density-constant isotropic family of " - "elementwise_gauss2d_scaling. Every arm is asked " - "for the same global relative tolerance rtol, and what the case measures " - "is the size and the time each one needs to reach it, so the arms are " - "comparable only because rtol is the same for all of them and the error " - "column is a check that they got there rather than the discriminator. " - "The size metric is n_params, the total number of stored core entries: a " - "bond dimension says nothing across the two representations here, since " - "a patched arm holds one train per patch and no single global rank " - "exists. For the patched arms n_params counts the free sites of each " - "patch only, the cores at the projected sites being one-hot copy " - "selectors that carry structure rather than data. The patched arms build " - "each input as a partitioned tensor train, split until every patch fits " - "under the per-patch rank cap, form the product patch pair by patch " - "pair, and budget the result once at the end with volume-proportional " - "absolute budgets, which is what makes shrinking patch norms harmless. " - "Which construction split the inputs is recorded per arm as input_path: " - "the default norm builds one global train per input and splits it by " - "Frobenius norms, so its input_build_secs includes that global build, " - "while tci runs a TCI per patch on the function and forms no global " - "train at all. The two global arms fit_treetn and aci are the case-3 " - "arms run tolerance-driven at the same rtol with no binding rank cap, and " - "each has its own N ceiling, since the uncapped global fit is orders of " - "magnitude more expensive than the interpolating arm. Input construction is " - "not part of the reported wall time: it is recorded separately as " - "input_build_secs, since one build is shared by every arm of an " - "instance. The fitted time exponent is measured against N." - ), -} - - -def load(profile_dir: Path): - cases = defaultdict(lambda: defaultdict(list)) - for path in sorted((profile_dir / "raw").glob("*.json")): - rec = json.loads(path.read_text()) - assert rec["schema_version"] == 1, f"unknown schema in {path}" - if "algorithm" not in rec: - continue # not a RunRecord (e.g. exported instance sidecar) - cases[rec["case"]][rec["algorithm"]].append(rec) - return cases - - -def xvalue(rec, xfield): - """Read the x axis value of one record, from params when asked for.""" - if xfield.startswith("params."): - return rec["params"][xfield[len("params."):]] - return rec[xfield] - -def fit_exponent(xs, ys): - xs, ys = np.asarray(xs, float), np.asarray(ys, float) - mask = (xs > 0) & (ys > 0) - if mask.sum() < 2: - return float("nan") - if np.ptp(np.log(xs[mask])) < 1e-9: - return float("nan") - p = np.polyfit(np.log(xs[mask]), np.log(ys[mask]), 1) - return p[0] - - -def render_gauss2d_scaling_extra(case, algos, profile_dir: Path): - """Case-4 only: the rank-versus-N answer the generic tables cannot show. - - The generic path plots everything against chi_in, which is the x axis of - every other case. Here chi_in is the dependent variable and N is the knob, - so this adds the instance table, the fitted exponent of chi_in against N, - and a log-log chi_in versus N plot. Returns extra Markdown lines. - """ - # One instance per N, shared by every arm, so read it off any one arm. - # Cheap check that this really is one instance per N: every arm must have - # been run over the same N set, or reading off one arm would misreport. - n_sets = {name: {rec["params"]["n_gauss"] for rec in rs} for name, rs in algos.items()} - assert len(set(map(frozenset, n_sets.values()))) == 1, f"arms disagree on N: {n_sets}" - recs = sorted(next(iter(algos.values())), key=lambda rec: rec["params"]["n_gauss"]) - ns = [rec["params"]["n_gauss"] for rec in recs] - chis = [rec["input_max_bond_dim"] for rec in recs] - lines = ["", "## Instances and input rank", "", - "| N | box half-width L | bits per variable R | input rank chi_in |", - "|---|---|---|---|"] - for rec in recs: - p = rec["params"] +def metadata(path: Path) -> dict[str, str]: + result = {} + for line in path.read_text().splitlines(): + if ":" in line: + key, value = line.split(":", 1) + result[key.strip()] = value.strip() + return result + + +def main(profile: Path) -> None: + records = [json.loads(path.read_text()) for path in sorted((profile / "raw").glob("*.json"))] + assert records, f"no JSON records in {profile / 'raw'}" + grouped = defaultdict(list) + for record in records: + assert record["schema_version"] == 1 + assert record["case"] in EXPECTED, record["case"] + assert record["algorithm"] in EXPECTED[record["case"]], record["algorithm"] + grouped[record["case"]].append(record) + assert set(grouped) == set(EXPECTED), set(grouped) + for case, arms in EXPECTED.items(): + assert {record["algorithm"] for record in grouped[case]} == arms + by_instance = defaultdict(list) + for record in grouped[case]: + key = record["params"].get("k_max", record["params"].get("n_gauss")) + by_instance[key].append(record["algorithm"]) + for key, actual in by_instance.items(): + assert Counter(actual) == Counter(arms), (case, key, actual) + for record in grouped["gaussian_elementwise"] + grouped["gaussian_mpo_contraction"]: + params = record["params"] + assert params["patch_cap"] == 128 + assert params["input_l2_rtol"] == 1e-6 + assert params["external_error_metric"] == "sampled_relative_l2" + assert record["max_error"] <= 1e-4 + run = metadata(profile / "run.yaml") + lines = [ + "# Tensor4all benchmark results", + "", + f"Profile: `{run['profile']}`. CPU: {run['chip']}. Threads: {run['threads']}. CPU affinity: {run['cpu_affinity']}. Source revision: `{run['repo_rev']}`. tensor4all-rs revision: `{run['tensor4all_rs_rev']}`.", + "", + "The source revision identifies the clean code that was measured. The commit adding these generated records necessarily follows that revision.", + "", + "All timings exclude input construction, cache I/O, format conversion, patch preparation, output conversion and accuracy evaluation. Gaussian inputs use independent two-dimensional interpolative decompositions, balanced pairwise addition, final relative-L2/SVD tolerance `1e-6`, and fixed patch cap 128.", + "", + "## Case 1: Fourier elementwise", + "", + "| input χ | K | arm | time (s) | sampled relative L2 | output χ | parameters |", + "|---:|---:|---|---:|---:|---:|---:|", + ] + for record in sorted(grouped["elementwise_fourier"], key=lambda item: (item["input_max_bond_dim"], item["params"]["k_max"], item["algorithm"])): lines.append( - f"| {p['n_gauss']} | {p['box_l']:.3f} | {p['r']} | " - f"{rec['input_max_bond_dim']} |" + f"| {record['input_max_bond_dim']} | {record['params']['k_max']} | {record['algorithm']} | {record['wall_time_median_secs']:.6f} | {record['max_error']:.3e} | {record['output_max_bond_dim']} | {record.get('n_params', '')} |" ) - # A single N (the CI smoke, or a probe) has no slope to fit, so say nothing - # rather than print "x = nan" and draw a one-point log-log plot. - if len(set(ns)) < 2: - lines += ["", "Only one N in this sweep, so there is no rank-versus-N " - "exponent to fit and no chi plot."] - return lines - - expo = fit_exponent(ns, chis) - lines += ["", f"Fitted over this sweep, chi_in grows like N^x with " - f"x = {expo:.2f}, against x = 0.5 for the sqrt(N) hypothesis " - f"and x = 1 for the linear one."] - - fig, ax = plt.subplots(figsize=(5, 4)) - ax.loglog(ns, chis, "o-", label=f"chi_in (N^{expo:.2f})") - ax.set_xlabel("number of Gaussians N") - ax.set_ylabel("input bond dimension chi_in") - ax.legend() - ax.grid(True, which="both", alpha=0.3) - fig.tight_layout() - fig.savefig(profile_dir / f"{case}-chi.svg") - plt.close(fig) - lines += ["", f"![chi](./{case}-chi.svg)"] - return lines - - -def family_of(rec): - """Instance family of one case-5 record. - - Records written before the case had two families carry no family field, and - they are all of the smooth one, so that is the fallback. - """ - return rec["params"].get("family", "smooth") - - -# Families of case 5, in report order: the anisotropic spikes are the default and -# the headline, the smooth family is case 4's and comes second. -FAMILY_ORDER = ["aniso", "smooth"] - -FAMILY_BLURB = { - "aniso": ( - "N anisotropic narrow spikes: minor width sigma fixed, aspect ratio " - "log-uniform in [1, rho_max] and orientation uniform in [0, pi) drawn per " - "spike, mean spacing held at a fixed number of minor widths so the box " - "grows like sqrt(N) and R resolves sigma to a quarter step. This is the " - "family the case defaults to: a field of small hard features whose global " - "rank climbs like N^0.5 through the sweep and then decelerates toward a " - "density-set plateau at larger N, while a patched representation is held " - "at its per-patch cap by construction. The isotropic control of the same " - "family, rho_max = 1, grows the same way, so the rank comes from the " - "density of narrow features rather than from the anisotropy." - ), - "smooth": ( - "N isotropic Gaussians of log-uniform inverse width at constant density, " - "case 4's family. Smooth everywhere, so there is no hard region for the " - "patching to isolate." - ), -} - - -def render_gauss2d_patched_extra(case, algos, profile_dir: Path): - """Case-5 only: the size and patch structure the generic tables cannot show. - - The generic path reports a time exponent and a worst error per arm, which for - an equal-accuracy case is a check rather than a result. What case 5 measures - is size against N at fixed accuracy, so this adds the instance table, the - per-arm size and patch-count table, and a parameter-count plot. All of it is - grouped by instance family, since the two families of the case are two - different problems and an arm's row means nothing without knowing which one it - ran on. Returns extra Markdown lines. - """ - families = sorted( - {family_of(rec) for recs in algos.values() for rec in recs}, - key=lambda name: (FAMILY_ORDER.index(name) if name in FAMILY_ORDER else len(FAMILY_ORDER), - name), - ) - lines = [] - for family in families: - per_family = { - name: [rec for rec in recs if family_of(rec) == family] - for name, recs in algos.items() - } - per_family = {name: recs for name, recs in per_family.items() if recs} - lines += ["", f"# Family: {family}", ""] - if family in FAMILY_BLURB: - lines += [FAMILY_BLURB[family], ""] - lines += render_patched_family(case, family, per_family, profile_dir) - return lines - - -def render_patched_family(case, family, algos, profile_dir: Path): - """The instance table, size table and parameter plot of one case-5 family.""" - lines = [] - # One instance per N, shared by every arm, so read it off any one arm. The - # patched fields come from a patched arm, the global chi_in from a global one. - patched = {name: recs for name, recs in algos.items() if name.startswith("patched_")} - globals_ = {name: recs for name, recs in algos.items() if not name.startswith("patched_")} - if patched: - recs = sorted(next(iter(patched.values())), key=lambda rec: rec["params"]["n_gauss"]) - # Every global arm of one N ran on the same two global trains, so any of - # them carries the instance columns. Merged over all of them rather than - # read off one, since the two baselines have different N ceilings and the - # cheaper one reaches points the expensive one does not. - by_n_global = {} - for recs_g in globals_.values(): - for rec in recs_g: - by_n_global.setdefault(rec["params"]["n_gauss"], rec) - lines += ["", "## Instances", "", - "| N | box half-width L | bits per variable R | input patches f, g | " - "input params, patched | patched build [s] | global chi_in | " - "input params, global | global build [s] |", - "|---|---|---|---|---|---|---|---|---|"] - for rec in recs: - p = rec["params"] - g = by_n_global.get(p["n_gauss"]) - gchi = str(g["input_max_bond_dim"]) if g else "not run" - gpar = f"{g['params']['input_n_params']}" if g else "not run" - gbuild = f"{g['input_build_secs']:.2f}" if g else "not run" + for case, title in [ + ("gaussian_elementwise", "Case 2: Gaussian elementwise, global versus patched"), + ("gaussian_mpo_contraction", "Case 3: Gaussian MPO-MPO contraction, global versus patched"), + ]: + lines += [ + "", + f"## {title}", + "", + "| input χ | raw χ | N | R | arm | time (s) | sampled relative L2 | input patches | input max patch χ | output patches | parameters | speedup |", + "|---:|---:|---:|---:|---|---:|---:|---:|---:|---:|---:|---:|", + ] + for record in sorted(grouped[case], key=lambda item: (item["input_max_bond_dim"], item["algorithm"])): + params = record["params"] + raw_chi = max(params["raw_left_chi"], params["raw_right_chi"]) + input_patches = params.get("input_patch_count", params.get("left_input_patch_count", 0) + params.get("right_input_patch_count", 0)) + input_patch_chi = params.get("input_max_patch_chi", max(params.get("left_input_max_patch_chi", 0), params.get("right_input_max_patch_chi", 0))) + speedup = params.get("speedup_vs_global", 1.0) lines.append( - f"| {p['n_gauss']} | {p['box_l']:.3f} | {p['r']} | " - f"{p['n_patches_f']}, {p['n_patches_g']} | {p['input_n_params']} | " - f"{rec['input_build_secs']:.2f} | {gchi} | {gpar} | {gbuild} |" + f"| {record['input_max_bond_dim']} | {raw_chi} | {params['n_gauss']} | {params['r']} | {record['algorithm']} | {record['wall_time_median_secs']:.6f} | {record['max_error']:.3e} | {input_patches} | {input_patch_chi} | {record.get('n_patches', 1)} | {record.get('n_params', '')} | {speedup:.3f} |" ) - - # The patched arms split their wall time between the patch-pair loop and the - # one final budgeting, and which half dominates is not guessable from the - # total, so those columns appear whenever a record carries them. A global arm - # has neither. - breakdown = any( - "pairs_secs" in rec["params"] for recs in algos.values() for rec in recs - ) - header = ["algorithm", "N", "median time [s]", "max relative error", "params", - "patches", "max patch bond"] - if breakdown: - header += ["pairs", "pairs time [s]", "truncate time [s]"] - lines += ["", "## Size and time at equal accuracy", "", - "| " + " | ".join(header) + " |", - "|" + "---|" * len(header)] - for algo, recs in sorted(algos.items()): - for rec in sorted(recs, key=lambda rec: rec["params"]["n_gauss"]): - patches = rec.get("n_patches") - bond = rec.get("max_patch_bond", rec["output_max_bond_dim"]) - row = ( - f"| {algo} | {rec['params']['n_gauss']} | " - f"{rec['wall_time_median_secs']:.4f} | {rec['max_error']:.2e} | " - f"{rec.get('n_params', 'n/a')} | {patches if patches else 'one train'} | " - f"{bond} |" - ) - if breakdown: - p = rec["params"] - if "pairs_secs" in p: - row += (f" {p['n_pairs']} | {p['pairs_secs']:.3f} | " - f"{p['truncate_secs']:.3f} |") - else: - row += " not patched | not patched | not patched |" - lines.append(row) - - fig, ax = plt.subplots(figsize=(5, 4)) - drew = False - for algo, recs in sorted(algos.items()): - recs = sorted(recs, key=lambda rec: rec["params"]["n_gauss"]) - ns = [rec["params"]["n_gauss"] for rec in recs] - params = [rec.get("n_params") for rec in recs] - if any(value is None for value in params) or len(set(ns)) < 2: - continue - expo = fit_exponent(ns, params) - ax.loglog(ns, params, "o-", label=f"{algo} (N^{expo:.1f})") - drew = True - if not drew: - plt.close(fig) - return lines - ax.set_xlabel("number of Gaussians N") - ax.set_ylabel("stored parameters of the product") - ax.set_title(f"family: {family}") - ax.legend() - ax.grid(True, which="both", alpha=0.3) - fig.tight_layout() - fig.savefig(profile_dir / f"{case}-params-{family}.svg") - plt.close(fig) - lines += ["", f"![params](./{case}-params-{family}.svg)"] - return lines - - -EXTRA_RENDER = { - # case name -> function(case, algos, profile_dir) -> extra Markdown lines. - # Case-keyed on purpose: the generic path stays untouched. - "elementwise_gauss2d_scaling": render_gauss2d_scaling_extra, - "elementwise_gauss2d_patched": render_gauss2d_patched_extra, -} - - -def series(case, algos): - """Series of the generic summary table and plots, one per line drawn. - - An arm name is enough everywhere except case 5, whose two instance families - share their arm names: a profile holding both would otherwise draw one line per - arm over the union of two different problems. Splitting the series by family - keeps each line one measurement. - """ - if case != "elementwise_gauss2d_patched": - return algos - families = {family_of(rec) for recs in algos.values() for rec in recs} - if len(families) < 2: - return algos - split = defaultdict(list) - for algo, recs in algos.items(): - for rec in recs: - split[f"{algo} ({family_of(rec)})"].append(rec) - return split - - -def render_case(case, algos, profile_dir: Path): - xfield, xlabel = X_AXIS[case] - xsym = X_SYMBOL.get(case, "chi") - elabel = ERROR_LABEL.get(case, "max error") - lines = [f"# {case}", "", - f"| algorithm | points | fitted time exponent | worst {elabel} |", - "|---|---|---|---|"] - fig_t, ax_t = plt.subplots(figsize=(5, 4)) - fig_e, ax_e = plt.subplots(figsize=(5, 4)) - for algo, recs in sorted(series(case, algos).items()): - recs = sorted(recs, key=lambda rec: xvalue(rec, xfield)) - xs = [xvalue(rec, xfield) for rec in recs] - ts = [rec["wall_time_median_secs"] for rec in recs] - es = [rec["max_error"] for rec in recs] - expo = fit_exponent(xs, ts) - lines.append(f"| {algo} | {len(recs)} | {expo:.2f} | {max(es):.2e} |") - ax_t.loglog(xs, ts, "o-", label=f"{algo} ({xsym}^{expo:.1f})") - ax_e.loglog(xs, es, "o-", label=algo) - if case in NOTES: - lines += ["", NOTES[case]] - if case in EXTRA_RENDER: - lines += EXTRA_RENDER[case](case, algos, profile_dir) - for ax, ylab in ((ax_t, "median wall time [s]"), (ax_e, elabel)): - ax.set_xlabel(xlabel) - ax.set_ylabel(ylab) - ax.legend() - ax.grid(True, which="both", alpha=0.3) - fig_t.tight_layout() - fig_e.tight_layout() - fig_t.savefig(profile_dir / f"{case}-time.svg") - fig_e.savefig(profile_dir / f"{case}-error.svg") - plt.close(fig_t) - plt.close(fig_e) - lines += ["", f"![time](./{case}-time.svg)", "", f"![error](./{case}-error.svg)", ""] - (profile_dir / f"{case}.md").write_text("\n".join(lines)) - print(f"wrote {profile_dir / (case + '.md')}") - - -def main(): - profile_dir = Path(sys.argv[1]) - cases = load(profile_dir) - if not cases: - sys.exit(f"no records under {profile_dir}/raw") - for case, algos in cases.items(): - if case in HAND_MAINTAINED_CASES: - report = profile_dir / f"{case}.md" - if not report.is_file(): - sys.exit(f"missing hand-maintained report {report}") - print(f"kept hand-maintained {report}") - continue - render_case(case, algos, profile_dir) + (profile / "report.md").write_text("\n".join(lines) + "\n") if __name__ == "__main__": - main() + if len(sys.argv) != 2: + raise SystemExit("usage: report.py result/") + main(Path(sys.argv[1])) diff --git a/scripts/report_mpo_input_scaling.py b/scripts/report_mpo_input_scaling.py deleted file mode 100644 index a43893b..0000000 --- a/scripts/report_mpo_input_scaling.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python3 -"""Render the case-6 anisotropic MPO input scaling report from raw JSON records.""" - -import json -import sys -from pathlib import Path - - -def pair(values, integer=False): - if integer: - return f"({values[0]:,}, {values[1]:,})" - return f"({values[0]:.2e}, {values[1]:.2e})" - - -def main() -> None: - if len(sys.argv) != 2: - raise SystemExit("usage: report_mpo_input_scaling.py result/") - profile = Path(sys.argv[1]) - paths = sorted( - (profile / "raw").glob("mpo_mpo_aniso_input-tci-n*-chi*.json"), - key=lambda path: json.loads(path.read_text())["n_gauss"], - ) - if not paths: - raise SystemExit(f"no case-6 input records under {profile / 'raw'}") - records = [json.loads(path.read_text()) for path in paths] - expected_caps = {512: 512, 4096: 512, 20480: 1280, 100000: 3072, 125000: 3584} - assert {record["n_gauss"] for record in records} == set(expected_caps) - for record in records: - assert record["case"] == "mpo_mpo_aniso_input" - assert record["input_generator"] == "tci" - assert record["sigma"] == 0.05 - assert record["rho_max"] == 8.0 - assert record["spacing"] == 3.0 - assert record["box_padding"] == 1.0 - assert record["r_extra"] == 0 - assert record["seed"] == 0 - assert record["input_tci_cap"] == expected_caps[record["n_gauss"]] - assert record["input_tci_rtol"] == 1e-8 - assert record["input_tci_local_abs_tol"] == 1e-12 - assert record["input_tci_initial_pivots"] == 8 - assert record["input_svd_l2_rtol"] == 1e-6 - assert record["patch_cap"] == 128 - assert record["max_input_chi"] == 1400 - assert record["input_error_samples"] == 256 - assert not record["input_cache_hit"] - assert max(record["input_sampled_relative_errors"]) <= record["input_sanity"] - - lines = [ - "# Anisotropic Gaussian MPO input and patch scaling", - "", - "This focused case-6 input study measures adaptive patching through compressed input bond dimension `chi_in ≈ 1000`. It uses the unchanged constant-density random anisotropic family (`sigma_minor = 0.05`, log-uniform aspect ratio in `[1, 8]`, independent angle, center, and positive weight per Gaussian).", - "", - "## Construction and accuracy", - "", - "The input pipeline is:", - "", - "1. fused two-variable TCI at relative tolerance `1e-8`;", - "2. global relative-L2 SVD truncation at `1e-6`;", - "3. adaptive input truncation with per-patch cap 128.", - "", - "TCI evaluates the same random mixture through a spatial index. A component is omitted only outside a radius where its individual Gaussian is below a common exponent threshold. Since all weights are positive, the sum of all omitted tails is bounded pointwise by `1e-12`. The committed sampled input errors include this bound and remain below `1e-5` after global SVD truncation.", - "", - "The alternative multiscale constructor builds one randomly rotated Gaussian directly. It marks points every half minor-axis standard deviation along the major-axis ridge as unsafe. The focused test covers `rho = 8`, a 45-degree rotation, and `R = 10`, and requires maximum sampled absolute error below `5e-8` at polynomial degree 28. Mixtures can be formed by adding these single-Gaussian QTTs with intermediate SVD compression. This path preserves the instance family but is not used for the large sweep because its per-Gaussian construction cost scales linearly with `N`; spatially indexed TCI reaches the requested rank regime efficiently.", - "", - "## Reproducible settings", - "", - "These input-only records were collected separately from the profile's earlier contraction sweep. The settings below, including core 0, are authoritative for these records rather than the contraction affinity in `run.yaml`.", - "", - "- Machine: AMD EPYC 7713P 64-Core Processor", - "- CPU affinity: core 0 (`taskset -c 0`)", - "- `RAYON_NUM_THREADS=1`, `OPENBLAS_NUM_THREADS=1`, `OMP_NUM_THREADS=1`", - "- `BENCH_INPUT_GENERATOR=tci`", - "- `BENCH_INPUT_TCI_RTOL=1e-8`", - "- `BENCH_TCI_LOCAL_ABS_TOL=1e-12`", - "- `BENCH_TCI_INITIAL_PIVOTS=8` (deterministic center-derived pivots)", - "- `BENCH_INPUT_SVD_RTOL=1e-6`", - "- `BENCH_PATCH_MAX_BOND=128`", - "- `BENCH_MAX_INPUT_CHI=1400`", - "- `BENCH_MAX_BOND=512, 512, 1280, 3072, 3584` for `N=512, 4096, 20480, 100000, 125000`", - "- one deterministic seed (`BENCH_SEED=0`)", - "- `BENCH_ERROR_SAMPLES=256` at every size", - "", - "Input generation, global SVD truncation, sampled validation, and adaptive patch preparation are all included in `preparation time`; no contraction is run (`BENCH_INPUT_ONLY=1`).", - "", - "## Results", - "", - "Each pair is `(left, right)` for the two independently drawn mixtures.", - "", - "| N | R | raw chi | compressed chi | global parameters | patches | max patch chi | patch parameters | sampled relative error | preparation time |", - "|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|", - ] - for record in records: - lines.append( - f"| {record['n_gauss']:,} | {record['r']} | {record['raw_input_chi']:,} | " - f"{record['input_chi']:,} | {pair(record['input_params'], True)} | " - f"{pair(record['input_patch_counts'], True)} | " - f"{pair(record['input_patch_max_bonds'], True)} | " - f"{pair(record['input_patch_params'], True)} | " - f"{pair(record['input_sampled_relative_errors'])} | " - f"{record['input_build_secs']:,.2f} s |" - ) - lines += [ - "", - "The compressed-rank plateau reaches `chi_in = 900`, within 10% of the requested `chi_in ≈ 1000` regime. Patch count grows stepwise from 1 to 6, 30, and 120 while every patch remains below cap 128. The `N = 125,000`, `R = 13` point increases raw rank and parameter count but remains on the same compressed-rank and patch-count plateau, so increasing `N` alone does not produce a smooth patch-count curve.", - "", - "Raw JSON records are in [`raw/`](raw/) with filenames `mpo_mpo_aniso_input-tci-n*-chi*.json`.", - "", - ] - (profile / "mpo_mpo_aniso_input_scaling.md").write_text("\n".join(lines)) - - -if __name__ == "__main__": - main() diff --git a/scripts/run_all.sh b/scripts/run_all.sh index e7291d2..cab0ef1 100755 --- a/scripts/run_all.sh +++ b/scripts/run_all.sh @@ -1,72 +1,55 @@ #!/usr/bin/env bash -# Usage: scripts/run_all.sh (e.g. mac-cpu) set -euo pipefail -PROFILE="${1:?usage: run_all.sh }" -ROOT="$(cd "$(dirname "$0")/.." && pwd)" -OUT="$ROOT/result/$PROFILE" -mkdir -p "$OUT/raw" -# cargo, uv and the relative report.py path below all resolve against the repo root. -cd "$ROOT" -# Wall times are only reproducible across runs if the thread count is pinned; -# the rayon default (all logical cores) varies by machine and load. Export -# RAYON_NUM_THREADS explicitly to override the single-thread default. -export RAYON_NUM_THREADS="${RAYON_NUM_THREADS:-1}" +if [[ $# -ne 1 ]]; then + echo "usage: scripts/run_all.sh " >&2 + exit 2 +fi -cargo build --release +profile=$1 +out="result/$profile" +raw="$out/raw" +core=${BENCH_CPU_CORE:-0} +mkdir -p "$raw" +rm -f "$raw"/*.json -echo "== running elementwise_fourier (full sweep, this takes a while)" -OUT_DIR="$OUT/raw" cargo run --release --bin elementwise_fourier -echo "== running elementwise_gauss2d (full sweep, this takes a while)" -OUT_DIR="$OUT/raw" cargo run --release --bin elementwise_gauss2d -echo "== running elementwise_gauss2d_scaling (full sweep, this takes a while)" -OUT_DIR="$OUT/raw" cargo run --release --bin elementwise_gauss2d_scaling -echo "== running elementwise_gauss2d_patched aniso (full sweep, this takes a while)" -OUT_DIR="$OUT/raw" cargo run --release --bin elementwise_gauss2d_patched -# The smooth family is part of the recorded case-5 story (the family where -# patching costs rather than saves), so the profile carries both. -echo "== running elementwise_gauss2d_patched smooth (full sweep, this takes a while)" -BENCH_FAMILY=smooth OUT_DIR="$OUT/raw" cargo run --release --bin elementwise_gauss2d_patched -echo "== running mpo_mpo_quantics (full sweep, this takes a while)" -OUT_DIR="$OUT/raw" cargo run --release --bin mpo_mpo_quantics +export RAYON_NUM_THREADS=1 +export OMP_NUM_THREADS=1 +export OPENBLAS_NUM_THREADS=1 +export MKL_NUM_THREADS=1 +export VECLIB_MAXIMUM_THREADS=1 +export OUT_DIR="$raw" -# repo_rev must name the source revision that actually produced this sweep, so a -# run from a modified tree is stamped with a -dirty suffix rather than a clean -# looking hash. Everything under result/ is excluded from that check: this script -# has just rewritten it, so it is dirty by construction and says nothing about -# which code ran. -DIRTY="$(git -C "$ROOT" diff --quiet -- ':(exclude)result' \ - && git -C "$ROOT" diff --cached --quiet -- ':(exclude)result' \ - || echo "-dirty")" +run() { + if command -v taskset >/dev/null 2>&1; then + taskset -c "$core" "$@" + else + "$@" + fi +} -# Wall times are machine bound for the memory heavy arms (README known issue 10), -# so the hardware that produced a sweep is part of the record, not decoration. -if [ "$(uname -s)" = "Darwin" ]; then - CHIP="$(sysctl -n machdep.cpu.brand_string)" - MEM_GB="$(( $(sysctl -n hw.memsize) / 1073741824 ))" -else - CHIP="$(lscpu 2>/dev/null | sed -n 's/^Model name: *//p' | head -1)" - CHIP="${CHIP:-unknown}" - MEM_GB="$(awk '/MemTotal/ {printf "%d", $2 / 1048576}' /proc/meminfo 2>/dev/null || echo unknown)" +repo_rev=$(git rev-parse HEAD) +if [[ -n $(git status --porcelain --untracked-files=no -- . ':!result') ]]; then + repo_rev="${repo_rev}-dirty" fi - -# No hostname: on a public repository a DHCP name leaks the operator's -# institution and location over time, and the machine identity is better -# carried by the profile name, the label below and the hardware fields. -# Set BENCH_MACHINE to override the label. -cat > "$OUT/run.yaml" </dev/null || true) +if [[ -z $chip ]] && command -v sysctl >/dev/null 2>&1; then + chip=$(sysctl -n machdep.cpu.brand_string 2>/dev/null || true) +fi +memory_gb=$(awk '/MemTotal/{printf "%.1f", $2/1024/1024}' /proc/meminfo 2>/dev/null || true) +cat > "$out/run.yaml" < anyhow::Result<()> { // This case is tolerance-driven (the arXiv setup): one tolerance // decides both the input compression and the product // truncation, and the ACI arm keeps the upstream absolute - // stopping rule. The fixed-budget cases 2, 3 and 4 separate the - // two instead. + // stopping rule. Gaussian records keep the input and operation + // tolerances separate. elementwise_product(algo, &a, &b, tol, max_bond, AciTolerance::Absolute) .expect("algorithm failed") }); - let max_error = max_error_vs_series(&out, &exact, r, n_error_samples, error_seed); + let max_error = + sampled_relative_l2_vs_series(&out, &exact, r, n_error_samples, error_seed); // The gate detects wrong results, not precision. Truncation is // norm-relative (the TT norm grows like 2^(R/2)), so the pointwise // error accumulates to ~100x tol at R=20, K=64 (measured 6.5e-7). @@ -115,7 +116,12 @@ fn main() -> anyhow::Result<()> { "k_max": k, "r": r, "max_bond": max_bond, "runs": runs, "warmups": warmups, "n_error_samples": n_error_samples, "error_seed": error_seed, - "error_metric": "max_abs", + "error_metric": "sampled_relative_l2", + "internal_tolerance_metric": if matches!(algo, ElementwiseAlgo::Aci) { + "aci_absolute_residual" + } else { + "relative_l2_svd" + }, // Part of the benchmark definition for the fit arm. "fit_nfullsweeps": FIT_NFULLSWEEPS, }), diff --git a/src/bin/elementwise_gauss2d.rs b/src/bin/elementwise_gauss2d.rs deleted file mode 100644 index 0b0f53c..0000000 --- a/src/bin/elementwise_gauss2d.rs +++ /dev/null @@ -1,277 +0,0 @@ -//! Case 3 runner: elementwise (Hadamard) product of two 2D quantics Gaussian -//! mixtures, swept over the number of bits per variable for each algorithm. -//! -//! Two independent mixtures are cross-interpolated into fused 2D quantics -//! tensor trains on `[-L, L)^2`, `r` sites of dimension 4, local index -//! `x_bit + 2 * y_bit` with the most significant bit first. The benchmarked -//! operation is `h = f * g` on the `2^r` by `2^r` grid, whose reference is -//! exact and pointwise: `h(x, y) = f(x, y) * g(x, y)`, with no quadrature and -//! no tail, so unlike case 2 this case has no reference error floor of its own. -//! -//! Fixed output budget decided by the rank cap alone, the same philosophy as -//! case 2: every arm runs with its maximum bond dimension capped at `chi_in`, -//! the larger of the two input ranks, and with an inert truncation tolerance, so -//! all arms genuinely exhaust the same output budget unless their exact rank is -//! smaller, and the error column is the discriminator. `BENCH_TOL` (default -//! 1e-8) scopes only the input TCI construction, so it defines `chi_in` and the -//! instance; `BENCH_CONTRACT_TOL` (default 1e-15) is what the arms receive and is -//! recorded as `contract_tol`. `BENCH_MAX_BOND` caps only the input TCI -//! construction. -//! -//! Arms, selectable with `BENCH_ALGOS`: `naive` (core-wise bond Kronecker -//! product then an SVD sweep, written locally on simplett primitives, so the -//! recorded engine is `local`), `zipup_treetn` and `fit_treetn` (both -//! `tensor4all_treetn::hadamard` through the bridge in `elementwise`), and -//! `aci` (`tensor4all_aci::elementwise`, adaptive cross interpolation of the -//! pointwise product). There is no simplett arm: `tensor4all-simplett` exposes -//! no elementwise product for tensor trains at the pinned revision, so unlike -//! case 2 this case cannot compare the two engines on the same algorithm. -//! -//! The `aci` arm needs one extra setting to sit in the same regime as the -//! SVD-based arms. Its stopping rule compares a pivot error against the -//! tolerance, so it runs with `scale_tolerance` enabled (`AciTolerance:: -//! ScaleRelative`, recorded as `aci_scale_tolerance` in the params of its -//! records) on top of the 1e-15 tolerance: the criterion is then scale-relative -//! and unreachable, and the rank cap is left in charge. One consequence at the -//! pinned rev: the rank-saturation early exit of tensor4all-rs#591 is included, -//! so ACI stops once the pivots stop improving rather than running to -//! `max_iters` under a criterion that can never fire, and the arm is cheap again. -//! -//! `fit_treetn` runs at a fixed sweep count (`elementwise::FIT_NFULLSWEEPS`), -//! shared with case 1 and recorded as `fit_nsweeps`: the fit cost is linear in -//! the sweep count, so its wall time is only comparable at a stated count. -//! -//! What the fixed budget measures, as observed over the default sweep r = 6 to -//! 14 with the pinned revision (chi_in of 53 and then 76 to 79 once the quantics -//! rank saturates): `naive`, `fit_treetn` and `aci` agree to the last reported -//! digit or close to it, from 3.6e-11 at r = 6 to about 1.7e-8 at r = 12, every -//! one of them at the full chi_out, since the rank cap is the only truncation -//! control. `zipup_treetn` collapses: it spends the same budget and still -//! returns errors of order one, 2.3e-1 to 7.9e-1 across the sweep, that is, an -//! answer with no correct digits. Its error also swings by a factor of two -//! between runs of the same configuration, since chi_in moves by one or two and -//! the truncation it forces is severe, so read it as order one rather than as a -//! number. The separation is much sharper than in -//! case 2, where the same single-pass truncation cost only four to five orders of -//! magnitude, because the exact elementwise product has rank up to chi_in squared -//! and a budget of chi_in discards almost all of it, whereas naive and fit reach -//! a near-optimal basis for the same budget. Raising the budget recovers zipup -//! smoothly (1.8e-7 at 8 chi_in, 3.9e-8 unconstrained at chi_out = 837), so -//! this is the price of the budget, not a broken arm. -//! On cost, `naive` is again the expensive one, forming the full chi_in-squared -//! bond before truncating: 0.05 s at r = 6, 3.3 s at r = 8 and 4 to 5 s at -//! r = 10 to 14, against 1.3 s for `fit_treetn` and 0.38 s for `zipup_treetn` -//! at r = 14. `aci` is the cheapest arm at every r by an order of magnitude, -//! 1 ms at r = 6 rising only to 75 ms at r = 14, because it never forms the -//! product it is approximating and because the pinned rev carries the -//! rank-saturation early exit. -//! The quantics construction wobble of README known issue 5 moves chi_in, and -//! with it the timings, by a little from run to run. Wall times of the naive arm -//! are machine bound at the larger r (README known issue 10), so compare them -//! only within one result profile. - -use std::path::PathBuf; -use t4a_bench::elementwise::{ - check_mixture_product_not_degenerate, elementwise_product, max_rel_error_vs_mixture_product, - tt_n_params, AciTolerance, ElementwiseAlgo, FIT_NFULLSWEEPS, -}; -use t4a_bench::gaussian::{to_quantics_fused_tt, GaussianMixture2D}; -use t4a_bench::harness::time_median; -use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; -use tensor4all_simplett::AbstractTensorTrain; - -const CASE: &str = "elementwise_gauss2d"; - -/// Sanity gate for the `zipup_treetn` arm, which cannot share `BENCH_SANITY`. -/// -/// At the fixed output budget the single-pass zip-up truncation of an -/// elementwise product is not merely less accurate, it fails outright: the -/// measured relative error at the pinned revision is of order one across the -/// default sweep, between 2e-1 and 8e-1 depending on r and on the run, against -/// 1e-8 or better for every other arm. That -/// is the headline result of this case, not a defect: given the same two inputs -/// and a budget of 8 chi_in the same arm reaches 1.8e-7, and unconstrained it -/// reaches 3.9e-8, so the algorithm is sound and the budget is what breaks it. -/// A relative error near one leaves no room for a gate that screens order-unity -/// wrongness, so this arm is gated only against a gross scale blow-up or a -/// non-finite result. -const ZIPUP_SANITY: f64 = 5.0; - -fn env_or(key: &str, default: T) -> T { - std::env::var(key) - .ok() - .and_then(|v| v.parse().ok()) - .unwrap_or(default) -} - -fn parse_algo(s: &str) -> ElementwiseAlgo { - match s { - "naive" => ElementwiseAlgo::Naive, - "zipup_treetn" => ElementwiseAlgo::Zipup, - "fit_treetn" => ElementwiseAlgo::Fit, - "aci" => ElementwiseAlgo::Aci, - other => panic!("unknown algorithm {other}"), - } -} - -fn main() -> anyhow::Result<()> { - let rs: Vec = std::env::var("BENCH_RS") - .unwrap_or_else(|_| "6,8,10,12,14".into()) - .split(',') - .map(|s| s.trim().parse().unwrap()) - .collect(); - let ngauss: usize = env_or("BENCH_NGAUSS", 8); - let box_l: f64 = env_or("BENCH_BOX_L", 6.0); - let alpha_lo: f64 = env_or("BENCH_ALPHA_LO", 0.5); - let alpha_hi: f64 = env_or("BENCH_ALPHA_HI", 8.0); - // Instance tolerance: this defines chi_in through the input TCI, and nothing - // else. It is what `RunRecord::tolerance` and the Julia-check metadata - // report, since both describe the inputs rather than the product. - let tol: f64 = env_or("BENCH_TOL", 1e-8); - // Product tolerance, pinned inert so the rank cap chi_in is the only binding - // truncation control for every arm. - let contract_tol: f64 = env_or("BENCH_CONTRACT_TOL", 1e-15); - let max_bond: usize = env_or("BENCH_MAX_BOND", 512); - let runs: usize = env_or("BENCH_RUNS", 3); - let warmups: usize = env_or("BENCH_WARMUPS", 0); - let seed: u64 = env_or("BENCH_SEED", 0); - // With the output budget fixed at chi_in, truncation error is the quantity - // being measured, not a defect, so the gate only screens order-unity - // wrongness rather than certifying precision. - let sanity: f64 = env_or("BENCH_SANITY", 1e-2); - let algos: Vec = std::env::var("BENCH_ALGOS") - .unwrap_or_else(|_| "naive,zipup_treetn,fit_treetn,aci".into()) - .split(',') - .map(|s| s.trim().to_string()) - .collect(); - let out_dir = - PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); - - // Accuracy check sampling, recorded in every record's params. - let n_error_samples: usize = 128; - let error_seed: u64 = seed.wrapping_add(99); - - let f = GaussianMixture2D::random(ngauss, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(1)); - let g = GaussianMixture2D::random(ngauss, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(2)); - - let mut failures = Vec::new(); - for &r in &rs { - let (fa, _step) = to_quantics_fused_tt(&f, r, box_l, tol, max_bond)?; - let (gb, _) = to_quantics_fused_tt(&g, r, box_l, tol, max_bond)?; - let input_chi = fa.rank().max(gb.rank()); - // Fail fast, before any timing: if the two mixtures do not overlap the - // relative error metric has no reference to normalize against. - let scales = - check_mixture_product_not_degenerate(&f, &g, r, box_l, n_error_samples, error_seed)?; - eprintln!( - "r={r} input_chi={input_chi} ref_scale={:.3e}", - scales.ref_scale - ); - - // An empty EXPORT_HDF5 counts as unset, so `EXPORT_HDF5=` disables export. - if let Some(dir) = std::env::var("EXPORT_HDF5").ok().filter(|d| !d.is_empty()) { - std::fs::create_dir_all(&dir)?; - let h5 = format!("{dir}/instance-r{r}.h5"); - // These are the exact trains the arms below consume, so the export - // is the benchmarked instance rather than a fresh TCI run. - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "f", &fa, false)?; - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "g", &gb, true)?; - let meta = serde_json::json!({ - "schema_version": 1, - "case": CASE, - "r": r, - "box_l": box_l, - "tolerance": tol, - "f": {"weights": f.weights, "alphas": f.alphas, "centers": f.centers}, - "g": {"weights": g.weights, "alphas": g.alphas, "centers": g.centers}, - }); - std::fs::write( - format!("{dir}/instance-r{r}.json"), - serde_json::to_string_pretty(&meta)?, - )?; - } - - for algo_name in &algos { - let algo = parse_algo(algo_name); - let (h, timing) = time_median(warmups, runs, || { - elementwise_product( - algo, - &fa, - &gb, - contract_tol, - input_chi, - AciTolerance::ScaleRelative, - ) - .expect("product failed") - }); - let max_error = - max_rel_error_vs_mixture_product(&h, &f, &g, r, box_l, n_error_samples, error_seed); - let rec = RunRecord { - schema_version: SCHEMA_VERSION, - case: CASE.into(), - algorithm: algo_name.clone(), - params: serde_json::json!({ - "r": r, "n_gauss": ngauss, "box_l": box_l, - "alpha_range": [alpha_lo, alpha_hi], "max_bond": max_bond, - // Output budget shared by every algorithm: the input rank. - "contract_max_bond": input_chi, - // Truncation tolerance the arms actually ran with, pinned - // inert so the cap above is what decides. The top-level - // `tolerance` field is the instance tolerance instead. - "contract_tol": contract_tol, - // True on the aci arm, whose stopping criterion is then - // scale-relative, so the inert tolerance above is - // unreachable for it too. The other arms are SVD-based and - // have no such switch. - "aci_scale_tolerance": matches!(algo, ElementwiseAlgo::Aci), - "runs": runs, "warmups": warmups, - "n_error_samples": n_error_samples, "error_seed": error_seed, - "error_metric": "max_rel_vs_analytic", - // Scales of the reference and of the two inputs at the same - // sampled points, so a degenerate instance is visible in the - // record rather than hidden inside the relative error. - "ref_scale": scales.ref_scale, - "input_scale_f": scales.input_scale_f, - "input_scale_g": scales.input_scale_g, - // Upstream engine that actually ran this arm. - "engine": algo.engine(), - // Part of the benchmark definition for the fit arm. - "fit_nsweeps": FIT_NFULLSWEEPS, - }), - seed, - tolerance: tol, - wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: h.rank(), - output_bond_dims: h.link_dims(), - n_params: Some(tt_n_params(&h)), - n_patches: None, - max_patch_bond: None, - rtol: None, - input_build_secs: None, - }; - write_record(&out_dir, &format!("{CASE}-{algo_name}-r{r}"), &rec)?; - eprintln!( - " {algo_name}: t={:.4}s rel_err={max_error:.2e} chi_out={}", - timing.median_secs, - h.rank() - ); - let gate = if matches!(algo, ElementwiseAlgo::Zipup) { - ZIPUP_SANITY - } else { - sanity - }; - if !max_error.is_finite() || max_error > gate { - failures.push(format!( - "{algo_name} r={r}: rel err {max_error:.2e} > {gate:.2e}" - )); - } - } - } - if !failures.is_empty() { - anyhow::bail!("sanity failures:\n{}", failures.join("\n")); - } - Ok(()) -} diff --git a/src/bin/elementwise_gauss2d_patched.rs b/src/bin/elementwise_gauss2d_patched.rs index a3bc9f9..7fcb3de 100644 --- a/src/bin/elementwise_gauss2d_patched.rs +++ b/src/bin/elementwise_gauss2d_patched.rs @@ -1,955 +1,461 @@ -//! Case 5 runner: patched elementwise product, the larger-N and rtol-controlled -//! version of case 4. -//! -//! Two instance families, `BENCH_FAMILY`, and the default is `aniso`. -//! -//! * `aniso`, the default, is `N` anisotropic narrow spikes: minor width -//! `BENCH_ANISO_SIGMA` fixed, aspect ratio log-uniform in -//! `[1, BENCH_ANISO_RHO_MAX]` and orientation uniform in `[0, pi)` drawn per -//! spike, weights `U[0.5, 1.5]`, centers uniform in `0.9` of the box. The mean -//! spacing is held at `BENCH_ANISO_SPACING` minor widths, so the box half-width -//! is `L = s sqrt(N) / 2` and `R` is the smallest bit count whose grid step -//! `2L / 2^R` resolves the minor width to a quarter. That family is the point of -//! the case: measured at these settings its global rank grows like `N^0.5`, 45 -//! at `N` = 8, 64 at 64, 88 at 128, 120 at 256, 182 at 512, then decelerating -//! toward saturation, 256 at 1024 and 2048 and 289 at 4096, all verified -//! converged in the tolerance and in `R` (that 256 equals the `R` = 9 geometric -//! bound is a coincidence). So a global representation pays a rank that grows -//! through the sweep and levels off at a density-set plateau, while a patched -//! one is held at the cap by construction; the contest is that plateau and the -//! growth toward it against the patch bookkeeping. -//! -//! The isotropic control of the same family is one knob away, -//! `BENCH_ANISO_RHO_MAX=1`, which draws circular spikes of one common shape. -//! Measured at the same settings it gives 49, 64, 94, 126, 196 and 256 over the -//! same `N`, which is the same growth: at this spacing-to-width ratio the rank -//! comes from the density of narrow spikes and not from the anisotropy. The -//! aspect ratio and the orientation are still drawn per spike because a family -//! of one common shape is a pure shift family, which is the degenerate case this -//! study should not rest on, but the measurement does not credit them with the -//! growth. -//! * `smooth` is case 4's family, kept reachable unchanged: `N` isotropic -//! Gaussians of log-uniform inverse width in `[BENCH_ALPHA_LO, BENCH_ALPHA_HI]` -//! at constant density, box half-width `L = L0 sqrt(N / N0)` and bit count -//! `R = R0 + round(log2(L / L0))`. It is smooth everywhere, so it has no hard -//! region for the patching to isolate, and the case-5 verdict on it is that -//! patching costs rather than saves. -//! -//! Both families hold the ratio of spacing to width fixed as `N` grows, which is -//! what keeps the degeneracy guard passing: the sampled product stays at a -//! constant fraction of `max|f| max|g|` instead of collapsing. The two mixtures of -//! an instance come from the seeds `BENCH_SEED + 1` and `BENCH_SEED + 2`, and the -//! family is recorded in every record's params. -//! -//! Representation. Each input is a `PartitionedTT`: a set of tensor trains over -//! disjoint subdomains, where a subdomain is a set of quantics digits held fixed, -//! so one fixed fused site is one quadrant of the box. A subdomain that does not -//! fit under the per-patch rank cap `BENCH_PATCH_MAX_BOND` is split again, so the -//! cap is honoured everywhere and a hard region of the box costs patches instead -//! of global rank. The product is then formed pair by pair over compatible patches -//! and budgeted once at the end by `truncate_adaptive`. Each patched record also -//! carries the cost breakdown of those two halves, `n_pairs`, `pairs_secs` and -//! `truncate_secs`, since which of them dominates is not guessable from the total. -//! -//! Input construction, `BENCH_PATCH_INPUT`. Two constructions produce that -//! patched input and the default is `norm`: build one global train per input -//! exactly as case 4 does, then hand it to `partitionedtt::add_with_patching`, -//! which truncates each subdomain against its volume share of the global squared -//! budget and splits whatever still exceeds the cap, choosing the split index by -//! `BENCH_PATCH_SPLIT`. No TCI runs in that splitting loop. The alternative, -//! `BENCH_PATCH_INPUT=tci`, is `partitionedtt::adaptiveinterpolate`, which never -//! forms a global train at all: it runs a TCI2 per patch on the function itself -//! and splits a patch whose own TCI does not converge under the cap. That is the -//! construction this case is eventually written for, since it is the one whose -//! cost never passes through a global rank. It used to be blocked by -//! an upstream TCI2 defect that returned site tensors with mismatched bonds, fixed -//! by tensor4all-rs#602 (README known issue 11); it now completes at smooth `N` = 32 -//! and 64 and at aniso `N` = 64. `norm` remains the default on the measurement: for -//! the same cap the `tci` path splits far harder, 514 and 622 input patches at -//! smooth `N` = 32 against 6 and 7, so it holds four times the input parameters and -//! returns four times the product parameters at the same accuracy. The two are not -//! the same measurement and `input_path` records which one ran: the `norm` path -//! pays for a global `chi_in` train before it splits, so its `input_build_secs` -//! includes that build, the bridge onto the case's site indices, and the -//! splitting. -//! -//! Control knob. Case 4 pins the output budget at `chi_out <= chi_in` and reads -//! the error that budget buys. That comparison has no meaning here, since a -//! patched representation has no single rank to cap: its size is a parameter -//! count spread over patches. Case 5 therefore fixes the accuracy instead, -//! `BENCH_RTOL` (default 1e-8), and reads the size and the time each arm needs to -//! reach it. Every arm is compared at one and the same `rtol`, and `n_params` is -//! the size metric, since it is the one quantity that means the same thing for a -//! single global train and for a set of patch trains. -//! -//! Both `aci` paths of this case, the global baseline and the per-patch engine, -//! read that `rtol` as an ABSOLUTE pivot budget rather than as the upstream -//! default scale-relative one, since the error this case reports is normalized by -//! the largest sampled magnitude of the whole box and a per-bond or per-patch -//! normalization is the per-region relative tolerance the patched budgeting -//! deliberately refuses. It is recorded as `aci_tolerance`, and README known -//! issue 13 records what the choice costs the size verdict. -//! -//! Arms. `patched_fit_treetn`, `patched_naive` and `patched_aci` are three of the -//! four engines of case 3 run on the projected patch trains instead of on the -//! global trains, so a difference between a patched arm and its global namesake is -//! the patching and not the engine. The fourth, `patched_zipup_treetn`, is -//! excluded from the defaults on cost alone and is one `BENCH_ALGOS` away. The -//! runner also measures the two global arms `fit_treetn` and `aci` at the same -//! `rtol` and with no rank cap binding, so the report can put patched and global -//! side by side at equal accuracy. On the norm path those two arms run on the very -//! trains the patched inputs were split out of, so one global construction is -//! counted once and shared. The two have their own `N` ceilings, since they differ -//! by two orders of magnitude in cost: see `max_n_with_fit_baseline` and -//! `max_n_with_aci_baseline`. Set `BENCH_BASELINES=0` to skip both. -//! -//! Input construction is timed and recorded separately from the product, as -//! `input_build_secs`, for both kinds of arm. The two measurements answer -//! different questions and the inputs are shared by every arm of an instance, so -//! adding them into the product time would count one build many times. A patched -//! arm on the norm path therefore reports the global build plus the splitting, -//! while a global arm on the same instance reports the global build alone. +//! Case 2: global and patched elementwise products of interpolative Gaussian QTTs. -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::Instant; +use tensor4all_partitionedtt::PatchSplitStrategy; +use tensor4all_simplett::AbstractTensorTrain; + use t4a_bench::elementwise::{ - check_product_not_degenerate, elementwise_product, max_rel_error_vs_product, tt_n_params, - AciTolerance, ElementwiseAlgo, FIT_NFULLSWEEPS, + elementwise_product, sampled_relative_l2_vs_product, tt_n_params, AciTolerance, ElementwiseAlgo, +}; +use t4a_bench::gaussian_input::{ + prepare_gaussian_pair, sampled_input_relative_l2, tensortrain_n_params, GaussianInputConfig, + INPUT_L2_RTOL, PATCH_CAP, }; -use t4a_bench::gaussian::{to_quantics_fused_tt_field, AnisoMixture2D, Field2D, GaussianMixture2D}; use t4a_bench::harness::time_median; use t4a_bench::patched::{ - fused_site_indices, max_patch_bond, max_rel_error_patched, parse_input_path, - parse_patched_engine, parse_split_strategy, patched_elementwise_with_stats, patched_input, - patched_input_from_global, split_strategy_label, total_params, NormPatchedInputOptions, - PatchedEngine, PatchedInputOptions, PatchedInputPath, PatchedProductOptions, + fused_site_indices, max_patch_bond, patched_elementwise, patched_input_from_global, + sampled_relative_l2_patched, total_params, NormPatchedInputOptions, PatchedEngine, + PatchedProductOptions, }; use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; -use tensor4all_simplett::AbstractTensorTrain; -const CASE: &str = "elementwise_gauss2d_patched"; +const CASE: &str = "gaussian_elementwise"; +const GLOBAL_MAX_BOND: usize = 4096; +const ERROR_SAMPLES: usize = 256; +const ERROR_SANITY: f64 = 1e-4; -fn env_or(key: &str, default: T) -> T { - std::env::var(key) +fn env_or(name: &str, default: T) -> T { + std::env::var(name) .ok() - .and_then(|v| v.parse().ok()) + .and_then(|value| value.parse().ok()) .unwrap_or(default) } -/// Which instance family the sweep runs on. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum Family { - /// Case 4's isotropic Gaussians at constant density. - Smooth, - /// Anisotropic narrow spikes at constant spacing-to-width ratio. - Aniso, -} - -impl Family { - fn label(self) -> &'static str { - match self { - Family::Smooth => "smooth", - Family::Aniso => "aniso", - } - } - - fn parse(name: &str) -> Option { - match name { - "smooth" => Some(Family::Smooth), - "aniso" => Some(Family::Aniso), - _ => None, - } - } - - /// Default sweep of the family. - /// - /// The smooth family keeps case 4's four points. The aniso family reaches - /// further because its inputs are far cheaper to build at these settings: its - /// grid is coarser at equal `N`, `R` = 9 at `N` = 512 against `R` = 15 for the - /// smooth family, so a global train costs seconds where the smooth one costs - /// minutes. Measured single-threaded at the pinned revision, the aniso default - /// sweep runs in about three minutes, of which the `N` = 512 point is two. - /// - /// `N` = 1024 is left out on cost alone, and it is an interesting point: there - /// the global rank reaches 256, the start of the density-set plateau (verified - /// converged in tolerance and in `R`). It costs 302 s on its own, of - /// which 242 s is `add_with_patching`, so it doubles the sweep and stays one - /// `BENCH_NS` away. - fn default_ns(self) -> &'static str { - match self { - Family::Smooth => "8,16,32,64", - Family::Aniso => "8,16,32,64,128,256,512", - } - } - - /// Largest `N` that still runs the global `fit_treetn` baseline. - /// - /// The uncapped tolerance-driven global fit is the most expensive arm of the - /// sweep, and it grows fast in `chi_in`. The ceiling is the last `N` measured - /// to stay under about two minutes for it, since a baseline that costs more - /// than everything else together would decide the sweep's cost without adding - /// a conclusion. On the norm path the global input trains are built anyway, - /// since the patches are split out of them, so what this skips is the product - /// and not the construction. - fn max_n_with_fit_baseline(self) -> usize { - match self { - Family::Smooth => 64, - // Measured single-threaded at the pinned revision, on the aniso - // family this arm is far cheaper than on the smooth one: 0.18 s at - // N = 64, 1.5 s at 128, 1.9 s at 256, 12.9 s at 512 and 25.1 s at - // 1024, at chi_in 64, 88, 120, 182 and 256. So it runs over the whole - // default sweep and one point beyond it, and 1024 is where the - // measurement stops rather than where the cost does. - Family::Aniso => 1024, - } - } - - /// Largest `N` that still runs the global `aci` baseline. - /// - /// Kept separate because the two baselines are not in the same cost class: - /// `aci` is interpolation-based and costs a fraction of a second where the fit - /// costs seconds to minutes (0.18 s at `N` = 1024 on the aniso family against - /// 25.1 s for the fit), so on that family it runs everywhere and gives the - /// report a global size to compare against at every point. - fn max_n_with_aci_baseline(self) -> usize { - match self { - Family::Smooth => 64, - Family::Aniso => usize::MAX, - } +fn main() -> anyhow::Result<()> { + let ns = std::env::var("BENCH_NS").unwrap_or_else(|_| "2,8,32,128".into()); + let ns = ns + .split(',') + .map(|value| value.trim().parse::().map_err(anyhow::Error::from)) + .collect::>>()?; + let out_dir = + PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); + let cache_dir = PathBuf::from( + std::env::var("BENCH_INPUT_CACHE_DIR").unwrap_or_else(|_| ".cache/inputs".into()), + ); + let refresh = env_or("BENCH_INPUT_CACHE_REFRESH", 0usize) != 0; + let runs = env_or("BENCH_RUNS", 1usize); + let warmups = env_or("BENCH_WARMUPS", 0usize); + let seed = env_or("BENCH_SEED", 0u64); + let aci_tolerance = env_or("BENCH_ACI_TOL", 1e-8_f64); + for n in ns { + run_point( + n, + seed, + aci_tolerance, + runs, + warmups, + &cache_dir, + refresh, + &out_dir, + )?; } + Ok(()) } -/// Box half-width and bit count for `n` Gaussians at constant density, the same -/// construction as case 4. Duplicated as a call into the case-4 binary is not -/// possible, and kept identical by `box_and_bits_matches_case_four`. -pub fn box_and_bits(n: usize, n0: usize, l0: f64, r0: usize) -> (f64, usize) { - let l = l0 * (n as f64 / n0 as f64).sqrt(); - let r = r0 as f64 + (l / l0).log2().round(); - (l, r.max(1.0) as usize) -} - -/// Box half-width and bit count of the anisotropic spike family. -/// -/// The mean spacing between spikes is held at `spacing` minor widths, so `N` -/// spikes at that spacing fill a box of half-width `L = s sqrt(N) / 2` with -/// `s = spacing * sigma`. Holding the spacing-to-width ratio fixed is what keeps -/// the elementwise product non degenerate as `N` grows: two independent draws -/// overlap by a constant fraction at every `N`. -/// -/// `R` is the smallest bit count whose grid step resolves the minor width to a -/// quarter, `2L / 2^R <= sigma / 4`, which is the resolution the case needs for -/// the sampled error to mean anything: a spike unresolved by the grid is not a -/// hard function, it is a missing one. -pub fn aniso_box_and_bits(n: usize, sigma: f64, spacing: f64) -> (f64, usize) { - let l = spacing * sigma * (n as f64).sqrt() / 2.0; - let r = (8.0 * l / sigma).log2().ceil().max(1.0) as usize; - (l, r) -} - -/// One patched input through the TCI-driven path, with the historical upstream -/// failure spelled out. -/// -/// Before the current pin the TCI2 of a single patch could return site tensors -/// whose bonds did not match, which surfaced here as an opaque dimension mismatch -/// from deep inside the construction. tensor4all-rs#602 fixed it (README known -/// issue 11) and this path now runs the sweep, but the diagnosis is kept: it is -/// what tells a reader on an older revision what they are looking at instead of -/// leaving them with an upstream stack trace. -fn build_input_tci( - mix: &M, - sites: &[tensor4all_core::DynIndex], - box_l: f64, - options: PatchedInputOptions, +#[allow(clippy::too_many_arguments)] +fn run_point( n: usize, -) -> anyhow::Result { - patched_input(mix, sites, box_l, options).map_err(|e| { - anyhow::anyhow!( - "TCI-driven patched input construction failed at N={n}: {e}. A dimension mismatch \ - here is README known issue 11, an upstream TCI2 defect that a single patch of some \ - instances triggered before the pin was moved to b160bb7, independent of \ - BENCH_PATCH_MAX_BOND and BENCH_PATCH_MAX_ITER. It is fixed at the current pin, so \ - on this revision the message means something new and is worth reporting upstream. \ - The default input construction of this case is the norm-driven one, \ - which does not go through that code at all: unset BENCH_PATCH_INPUT to use it." - ) - }) -} - -/// Everything the two families share, parsed once from the environment. -struct Config { - family: Family, - rtol: f64, - patch_max_bond: usize, - input_path: PatchedInputPath, - split_strategy: tensor4all_partitionedtt::PatchSplitStrategy, - patch_max_iter: usize, - product_max_bond: usize, - global_max_bond: usize, + seed: u64, + aci_tolerance: f64, runs: usize, warmups: usize, - seed: u64, - sanity: f64, - baselines: bool, - engines: Vec, - out_dir: PathBuf, - n_error_samples: usize, - error_seed: u64, -} + cache_dir: &Path, + refresh: bool, + out_dir: &Path, +) -> anyhow::Result<()> { + let config = GaussianInputConfig { + n, + sigma_minor: 0.05, + rho_max: 8.0, + spacing: 3.0, + polynomial_degree: 28, + interpolation_tolerance: 1e-10, + addition_tolerance: 1e-10, + seed, + cache_dir: cache_dir.to_path_buf(), + refresh, + }; + let input = prepare_gaussian_pair(&config)?; + let (left_input_error, right_input_error) = + sampled_input_relative_l2(&input, ERROR_SAMPLES, seed.wrapping_add(41))?; + anyhow::ensure!( + left_input_error <= ERROR_SANITY && right_input_error <= ERROR_SANITY, + "input error exceeds sanity gate: ({left_input_error:.3e}, {right_input_error:.3e})" + ); + let sites = fused_site_indices(input.r); + let patch_start = Instant::now(); + let patch_options = NormPatchedInputOptions { + rtol: INPUT_L2_RTOL, + max_bond_dim: PATCH_CAP, + strategy: PatchSplitStrategy::ExactParameterGain, + }; + let patched_left = patched_input_from_global(&input.left, &sites, patch_options)?; + let patched_right = patched_input_from_global(&input.right, &sites, patch_options)?; + let patch_secs = patch_start.elapsed().as_secs_f64(); + let input_chi = input.left.rank().max(input.right.rank()); + let input_params = tensortrain_n_params(&input.left) + tensortrain_n_params(&input.right); + let patch_params = total_params(&patched_left, &sites)? + total_params(&patched_right, &sites)?; + let patch_count = patched_left.len() + patched_right.len(); + let input_max_patch = max_patch_bond(&patched_left).max(max_patch_bond(&patched_right)); + anyhow::ensure!(input_max_patch <= PATCH_CAP, "input patch cap exceeded"); -#[allow(clippy::too_many_lines)] -fn main() -> anyhow::Result<()> { - let family = Family::parse( - std::env::var("BENCH_FAMILY") - .unwrap_or_else(|_| "aniso".into()) - .trim(), - ) - .unwrap_or_else(|| panic!("BENCH_FAMILY must be aniso or smooth")); - let ns: Vec = std::env::var("BENCH_NS") - .unwrap_or_else(|_| family.default_ns().into()) - .split(',') - .map(|s| s.trim().parse().unwrap()) - .collect(); - // Smooth family knobs, case 4's. - let l0: f64 = env_or("BENCH_L0", 6.0); - let n0: usize = env_or("BENCH_N0", 8); - let r0: usize = env_or("BENCH_R0", 10); - let alpha_lo: f64 = env_or("BENCH_ALPHA_LO", 0.5); - let alpha_hi: f64 = env_or("BENCH_ALPHA_HI", 8.0); - // Aniso family knobs. The minor width is what the grid has to resolve and the - // spacing is quoted in minor widths, so these three numbers fix the box, the - // bit count and the overlap of the product at every N. - let aniso_sigma: f64 = env_or("BENCH_ANISO_SIGMA", 0.05); - let aniso_rho_max: f64 = env_or("BENCH_ANISO_RHO_MAX", 8.0); - let aniso_spacing: f64 = env_or("BENCH_ANISO_SPACING", 3.0); - // The one accuracy knob of the case: it sets the input TCI tolerance of both - // representations and the output budget of both products. - let rtol: f64 = env_or("BENCH_RTOL", 1e-8); - // Per-patch rank cap. A patch that cannot be brought below it is split, so - // this is what decides how deep the patch tree goes. - let patch_max_bond: usize = env_or("BENCH_PATCH_MAX_BOND", 64); - // Which construction produces the patched inputs. The default is the - // norm-driven splitting of a global train; `tci` is the adaptiveinterpolate - // path, which runs at the pinned revision and is not the default because it - // splits far harder for the same cap (README known issue 11). - let input_path = parse_input_path( - std::env::var("BENCH_PATCH_INPUT") - .unwrap_or_else(|_| "norm".into()) - .trim(), - ) - .unwrap_or_else(|| panic!("BENCH_PATCH_INPUT must be norm or tci")); - // How the norm-driven path picks the site to split. The upstream default - // `gain` forms and budget-truncates the children of every candidate site and - // keeps the cheapest; `sequential` takes the first unprojected site of the - // patch order, so the splitting runs strictly coarse to fine. Ignored by the - // tci path, whose splitting is always sequential in the patch order. - let split_strategy = parse_split_strategy( - std::env::var("BENCH_PATCH_SPLIT") - .unwrap_or_else(|_| "gain".into()) - .trim(), - ) - .unwrap_or_else(|| panic!("BENCH_PATCH_SPLIT must be gain or sequential")); - // Half-sweep limit of each patch's TCI run on the tci path. A run that stops - // at its iteration limit is not converged, so its patch is split whatever its - // rank was, which is why this knob exists at all: if it bound, the patch tree - // would be a measurement of it rather than of the rank cap. It does not bind. - // Measured at N = 8 on the smooth family, raising it from the upstream 20 to - // 200 left the patch counts and the patch ranks unchanged and cost six times - // the build time. - let patch_max_iter: usize = env_or("BENCH_PATCH_MAX_ITER", 20); - // Rank cap of the per-patch product and of the budgeted output. Left - // non-binding by default at the exact product rank of two capped patches, so - // that rtol is the only thing that truncates; the runner fails if it binds. - let product_max_bond: usize = - env_or("BENCH_PATCH_OUT_MAX_BOND", patch_max_bond * patch_max_bond); - // Construction cap of the global input trains, and rank cap of the global - // baseline product. Non-binding by design, as above. It applies to the global - // baselines and, on the norm path, to the global trains the patched inputs are - // split out of, which are one and the same trains. - let global_max_bond: usize = env_or("BENCH_MAX_BOND", 512); - // One timed pass per arm, against three in the other cases. This case is the - // most expensive per point and its arms cost tens of seconds each at the top - // of the default sweep, so a median of three would triple a sweep that is - // already the longest in the repository, and it would buy little: an arm here - // does one deterministic pass of real work over many patch pairs, and the - // spread of three passes measured at N = 8 is about three percent (2.67, 2.72 - // and 2.77 s for patched_fit_treetn), well under the spread between two - // constructions of the same instance, whose input TCI is not bit-reproducible: - // the same arm on a rebuilt instance moved from 2.85e-8 to 3.83e-8 in error. - // Raise it if you want the median. - let runs: usize = env_or("BENCH_RUNS", 1); - let warmups: usize = env_or("BENCH_WARMUPS", 0); - let seed: u64 = env_or("BENCH_SEED", 0); - // Nothing here spends a budget it cannot afford, so every arm is expected to - // land near rtol and the gate only screens order-unity wrongness, as in the - // other cases. - let sanity: f64 = env_or("BENCH_SANITY", 1e-2); - let baselines: usize = env_or("BENCH_BASELINES", 1); - // `patched_zipup_treetn` is excluded from the default arms, the way case 4 - // excludes `naive`: on the norm path a patch carries a rank near the global - // one, and a single-pass zip-up of two such patches with no binding output cap - // has to form the full product bond before it truncates. Measured at N = 8 on - // the smooth family, where the construction returns one patch, it costs 98 s - // per pass against 3.5 s for each of the other three arms and returns the same - // product to every reported digit, so it would dominate the default sweep - // without adding a conclusion. Run it explicitly through BENCH_ALGOS. - let engines: Vec = std::env::var("BENCH_ALGOS") - .unwrap_or_else(|_| "patched_fit_treetn,patched_naive,patched_aci".into()) - .split(',') - .map(|name| { - parse_patched_engine(name.trim()) - .unwrap_or_else(|| panic!("unknown patched arm {name}")) - }) - .collect(); - let out_dir = - PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); + let (global_fit_result, global_fit_timing) = time_median(warmups, runs, || { + elementwise_product( + ElementwiseAlgo::Fit, + &input.left, + &input.right, + INPUT_L2_RTOL, + GLOBAL_MAX_BOND, + AciTolerance::Absolute, + ) + }); + let global_fit = global_fit_result?; + let global_fit_error = sampled_relative_l2_vs_product( + &global_fit, + &input.left_mixture, + &input.right_mixture, + input.r, + input.box_l, + ERROR_SAMPLES, + seed.wrapping_add(99), + ); + anyhow::ensure!( + global_fit_error <= ERROR_SANITY, + "global fit error {global_fit_error:.3e}" + ); + write_global_record( + out_dir, + "global_fit", + &input, + &config, + input_chi, + input_params, + patch_count, + input_max_patch, + patch_params, + patch_secs, + left_input_error, + right_input_error, + INPUT_L2_RTOL, + "relative_l2_svd", + &global_fit, + global_fit_error, + &global_fit_timing, + )?; - let cfg = Config { - family, - rtol, - patch_max_bond, - input_path, - split_strategy, - patch_max_iter, - product_max_bond, - global_max_bond, - runs, - warmups, - seed, - sanity, - baselines: baselines != 0, - engines, + let (patched_fit_result, patched_fit_timing) = time_median(warmups, runs, || { + patched_elementwise( + &patched_left, + &patched_right, + &sites, + PatchedProductOptions { + engine: PatchedEngine::FitTreetn, + product_tol: 1e-8, + product_max_bond_dim: PATCH_CAP, + rtol: INPUT_L2_RTOL, + max_bond_dim: PATCH_CAP, + }, + ) + }); + let patched_fit = patched_fit_result?; + let patched_fit_error = sampled_relative_l2_patched( + &patched_fit, + &sites, + &input.left_mixture, + &input.right_mixture, + input.box_l, + ERROR_SAMPLES, + seed.wrapping_add(99), + )?; + anyhow::ensure!( + patched_fit_error <= ERROR_SANITY, + "patched fit error {patched_fit_error:.3e}" + ); + write_patched_record( out_dir, - // Accuracy check sampling, recorded in every record's params, and the same - // as case 4's so the two cases report the same kind of number. - n_error_samples: 128, - error_seed: seed.wrapping_add(99), - }; + "patched_fit", + &input, + &config, + input_chi, + input_params, + patch_count, + input_max_patch, + patch_params, + patch_secs, + left_input_error, + right_input_error, + INPUT_L2_RTOL, + "relative_l2_svd", + &patched_fit, + patched_fit_error, + &patched_fit_timing, + global_fit_timing.median_secs, + &sites, + )?; - let mut failures = Vec::new(); - for &n in &ns { - match family { - Family::Smooth => { - let (box_l, r) = box_and_bits(n, n0, l0, r0); - let f = - GaussianMixture2D::random(n, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(1)); - let g = - GaussianMixture2D::random(n, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(2)); - run_point( - &cfg, - n, - box_l, - r, - &f, - &g, - serde_json::json!({ - "l0": l0, "n0": n0, "r0": r0, - "alpha_range": [alpha_lo, alpha_hi], - }), - &mut failures, - )?; - } - Family::Aniso => { - let (box_l, r) = aniso_box_and_bits(n, aniso_sigma, aniso_spacing); - let f = AnisoMixture2D::random( - n, - box_l, - aniso_sigma, - aniso_rho_max, - seed.wrapping_add(1), - ); - let g = AnisoMixture2D::random( - n, - box_l, - aniso_sigma, - aniso_rho_max, - seed.wrapping_add(2), - ); - run_point( - &cfg, - n, - box_l, - r, - &f, - &g, - serde_json::json!({ - "aniso_sigma_minor": aniso_sigma, - "aniso_rho_max": aniso_rho_max, - "aniso_spacing_widths": aniso_spacing, - }), - &mut failures, - )?; - } - } - } - if !failures.is_empty() { - anyhow::bail!("sanity failures:\n{}", failures.join("\n")); - } + let (global_aci_result, global_aci_timing) = time_median(warmups, runs, || { + elementwise_product( + ElementwiseAlgo::Aci, + &input.left, + &input.right, + aci_tolerance, + GLOBAL_MAX_BOND, + AciTolerance::ScaleRelative, + ) + }); + let global_aci = global_aci_result?; + let global_aci_error = sampled_relative_l2_vs_product( + &global_aci, + &input.left_mixture, + &input.right_mixture, + input.r, + input.box_l, + ERROR_SAMPLES, + seed.wrapping_add(99), + ); + anyhow::ensure!( + global_aci_error <= ERROR_SANITY, + "global ACI error {global_aci_error:.3e}" + ); + write_global_record( + out_dir, + "global_aci", + &input, + &config, + input_chi, + input_params, + patch_count, + input_max_patch, + patch_params, + patch_secs, + left_input_error, + right_input_error, + aci_tolerance, + "aci_scale_relative_residual", + &global_aci, + global_aci_error, + &global_aci_timing, + )?; + + let (patched_aci_result, patched_aci_timing) = time_median(warmups, runs, || { + patched_elementwise( + &patched_left, + &patched_right, + &sites, + PatchedProductOptions { + engine: PatchedEngine::Aci, + product_tol: aci_tolerance, + product_max_bond_dim: PATCH_CAP, + rtol: INPUT_L2_RTOL, + max_bond_dim: PATCH_CAP, + }, + ) + }); + let patched_aci = patched_aci_result?; + let patched_aci_error = sampled_relative_l2_patched( + &patched_aci, + &sites, + &input.left_mixture, + &input.right_mixture, + input.box_l, + ERROR_SAMPLES, + seed.wrapping_add(99), + )?; + anyhow::ensure!( + patched_aci_error <= ERROR_SANITY, + "patched ACI error {patched_aci_error:.3e}" + ); + write_patched_record( + out_dir, + "patched_aci", + &input, + &config, + input_chi, + input_params, + patch_count, + input_max_patch, + patch_params, + patch_secs, + left_input_error, + right_input_error, + aci_tolerance, + "aci_absolute_patch_residual_then_global_l2", + &patched_aci, + patched_aci_error, + &patched_aci_timing, + global_aci_timing.median_secs, + &sites, + )?; Ok(()) } -/// One instance: build both representations, run every arm, write the records. -/// -/// Generic over the family, so the patched inputs, the degeneracy guard, the error -/// metric and both global baselines run on one code path for both of them and a -/// difference between two families is the instance and not the harness. -#[allow(clippy::too_many_lines, clippy::too_many_arguments)] -fn run_point( - cfg: &Config, - n: usize, - box_l: f64, - r: usize, - f: &M, - g: &M, - family_params: serde_json::Value, - failures: &mut Vec, -) -> anyhow::Result<()> { - let rtol = cfg.rtol; - // Fail fast, before any timing: the box grows with N at fixed density, so this - // is where too narrow a Gaussian or too sparse a spike field would empty the - // product and make the relative error meaningless. - let scales = check_product_not_degenerate(f, g, r, box_l, cfg.n_error_samples, cfg.error_seed)?; +#[allow(clippy::too_many_arguments)] +fn common_params( + input: &t4a_bench::gaussian_input::GaussianInputPair, + config: &GaussianInputConfig, + input_params: usize, + patch_count: usize, + input_max_patch: usize, + patch_params: usize, + patch_secs: f64, + left_input_error: f64, + right_input_error: f64, + internal_tolerance: f64, + tolerance_metric: &str, +) -> serde_json::Value { + serde_json::json!({ + "n_gauss": config.n, "r": input.r, "box_l": input.box_l, + "sigma_minor": config.sigma_minor, "rho_max": config.rho_max, + "spacing": config.spacing, "polynomial_degree": config.polynomial_degree, + "interpolation_tolerance": config.interpolation_tolerance, + "addition_tolerance": config.addition_tolerance, + "input_l2_rtol": INPUT_L2_RTOL, "patch_cap": PATCH_CAP, + "raw_left_chi": input.raw_left_chi, "raw_right_chi": input.raw_right_chi, + "left_chi": input.left.rank(), "right_chi": input.right.rank(), + "raw_left_params": input.raw_left_params, "raw_right_params": input.raw_right_params, + "input_params": input_params, "input_patch_count": patch_count, + "input_max_patch_chi": input_max_patch, "input_patch_params": patch_params, + "cache_key": input.cache_key, "cache_hit": input.cache_hit, + "cache_load_secs": input.cache_load.as_secs_f64(), + "input_build_secs": input.build.as_secs_f64(), + "input_compression_secs": input.compression.as_secs_f64(), + "patch_build_secs": patch_secs, + "left_input_sampled_relative_l2": left_input_error, + "right_input_sampled_relative_l2": right_input_error, + "error_samples": ERROR_SAMPLES, + "internal_tolerance": internal_tolerance, + "internal_tolerance_metric": tolerance_metric, + "external_error_metric": "sampled_relative_l2" + }) +} - let sites = fused_site_indices(r); - let t0 = Instant::now(); - // The global trains of the norm path, kept so the baselines can be measured on - // the very trains the patched inputs were split out of instead of on a second, - // identical construction. `None` on the tci path, which builds no global train - // and leaves that to the baselines. - let mut global_inputs = None; - // Rank of those global trains, recorded with the patched arms of the norm - // path: it is the size the patching starts from, so it belongs in the record - // even at the N where no global baseline arm runs. - let mut norm_global_chi = None; - let (fp, gp) = match cfg.input_path { - PatchedInputPath::NormDriven => { - // Case 4's input construction, tolerance and cap, so the patched - // inputs of this case start from the same trains that case measures. - // Its own build time is kept separately, since it is what the - // baselines pay and only a part of what the patched arms pay. - let t_global = Instant::now(); - let (fa, _step) = to_quantics_fused_tt_field(f, r, box_l, rtol, cfg.global_max_bond)?; - let (gb, _) = to_quantics_fused_tt_field(g, r, box_l, rtol, cfg.global_max_bond)?; - let global_build_secs = t_global.elapsed().as_secs_f64(); - let chi_in = fa.rank().max(gb.rank()); - norm_global_chi = Some(chi_in); - // Case 4's loud failure, and it matters more here: a cap-limited - // global train is not the tolerance-limited object the patched - // representation is supposed to be split out of, so everything - // downstream of it would be a measurement of the cap. - if chi_in >= cfg.global_max_bond { - failures.push(format!( - "n={n}: the global input chi {chi_in} of the norm-driven patched \ - construction reached the construction cap \ - BENCH_MAX_BOND={}, so the train the patches were split out of is \ - cap-limited rather than tolerance-limited", - cfg.global_max_bond - )); - } - // The splitting is relative to the norm of the whole function, not per - // patch: `add_with_patching` spends rtol^2 ||F||^2 over the patches by - // volume, so a patch in a near-empty corner of the box is never asked - // for eight relative digits of a quantity that contributes nothing to - // the global norm. - let options = NormPatchedInputOptions { - rtol, - max_bond_dim: cfg.patch_max_bond, - strategy: cfg.split_strategy, - }; - let fp = patched_input_from_global(&fa, &sites, options)?; - let gp = patched_input_from_global(&gb, &sites, options)?; - global_inputs = Some((fa, gb, global_build_secs)); - (fp, gp) - } - PatchedInputPath::TciDriven => { - // The per-patch TCI tolerance is absolute, rtol times the sampled - // scale of the function, rather than relative per patch, for the same - // reason: a patch in a near-empty corner has to be allowed to converge - // at rank one. - let fp = build_input_tci( - f, - &sites, - box_l, - PatchedInputOptions { - abs_tol: rtol * scales.input_scale_f, - max_bond_dim: cfg.patch_max_bond, - max_iter: cfg.patch_max_iter, - seed: cfg.seed.wrapping_add(1), - }, - n, - )?; - let gp = build_input_tci( - g, - &sites, - box_l, - PatchedInputOptions { - abs_tol: rtol * scales.input_scale_g, - max_bond_dim: cfg.patch_max_bond, - max_iter: cfg.patch_max_iter, - seed: cfg.seed.wrapping_add(2), - }, - n, - )?; - (fp, gp) - } - }; - let patched_build_secs = t0.elapsed().as_secs_f64(); - let patched_input_bond = max_patch_bond(&fp).max(max_patch_bond(&gp)); - let patched_input_params = total_params(&fp, &sites)? + total_params(&gp, &sites)?; - eprintln!( - "family={} n={n} box_l={box_l:.3} r={r} ref_scale={:.3e} input_path={} split={} \ - patches f={} g={} input_bond={patched_input_bond} \ - input_params={patched_input_params} build={patched_build_secs:.3}s", - cfg.family.label(), - scales.ref_scale, - cfg.input_path.label(), - split_strategy_label(cfg.split_strategy), - fp.len(), - gp.len() +#[allow(clippy::too_many_arguments)] +fn write_global_record( + out_dir: &Path, + arm: &str, + input: &t4a_bench::gaussian_input::GaussianInputPair, + config: &GaussianInputConfig, + input_chi: usize, + input_params: usize, + patch_count: usize, + input_max_patch: usize, + patch_params: usize, + patch_secs: f64, + left_input_error: f64, + right_input_error: f64, + internal_tolerance: f64, + tolerance_metric: &str, + output: &tensor4all_simplett::SimpleTensorTrain, + error: f64, + timing: &t4a_bench::harness::Timing, +) -> anyhow::Result<()> { + let params = common_params( + input, + config, + input_params, + patch_count, + input_max_patch, + patch_params, + patch_secs, + left_input_error, + right_input_error, + internal_tolerance, + tolerance_metric, ); - - for &engine in &cfg.engines { - let arm = engine.arm_name(); - let options = PatchedProductOptions { - engine, - // Safely below the budget the result is judged at: the real budgeting - // is done once at the end by truncate_adaptive, which is the only - // place that knows the output norm and the patch volumes. - product_tol: rtol * 1e-2, - product_max_bond_dim: cfg.product_max_bond, - rtol, - max_bond_dim: cfg.product_max_bond, - }; - let ((h, stats), timing) = time_median(cfg.warmups, cfg.runs, || { - patched_elementwise_with_stats(&fp, &gp, &sites, options) - .expect("patched product failed") - }); - let max_error = - max_rel_error_patched(&h, &sites, f, g, box_l, cfg.n_error_samples, cfg.error_seed)?; - let n_params = total_params(&h, &sites)?; - let out_bond = max_patch_bond(&h); - let mut params = serde_json::json!({ - "n_gauss": n, "box_l": box_l, "r": r, - "family": cfg.family.label(), - "arm_kind": "patched", - // Which construction produced the patched inputs, and how it chose - // the split site. The two paths are different measurements, so this - // is part of what identifies the run. - "input_path": cfg.input_path.label(), - "split_strategy": split_strategy_label(cfg.split_strategy), - // Per-patch cap that decides how deep the patch tree goes. - "patch_max_bond": cfg.patch_max_bond, - // Only the tci path runs a TCI per patch, so this is inert on the - // norm path and recorded for completeness. - "patch_max_iter": cfg.patch_max_iter, - // Per-patch product tolerance and cap, both deliberately - // non-binding: rtol and truncate_adaptive decide the output. - "product_tol": rtol * 1e-2, - "product_max_bond": cfg.product_max_bond, - "n_patches_f": fp.len(), "n_patches_g": gp.len(), - "input_n_params": patched_input_params, - // Rank of the global trains the norm path split, null on the tci - // path, which never builds one. - "input_global_chi": norm_global_chi, - // Cost breakdown of the last timed pass: the pair loop against the - // one final budgeting. Which half dominates changes with the family - // and with N, so the total alone is not interpretable. - "n_pairs": stats.n_pairs, - "pairs_secs": stats.pairs_secs, - "truncate_secs": stats.truncate_secs, - "runs": cfg.runs, "warmups": cfg.warmups, - "n_error_samples": cfg.n_error_samples, "error_seed": cfg.error_seed, - "error_metric": "max_rel_vs_analytic", - "ref_scale": scales.ref_scale, - "input_scale_f": scales.input_scale_f, - "input_scale_g": scales.input_scale_g, - "engine": engine.engine(), - // The per-patch aci engine runs on an absolute budget, as the global - // baseline does, so the two are asked for the same thing. - "aci_tolerance": "absolute", - "fit_nsweeps": FIT_NFULLSWEEPS, - // The output is a set of patch trains, so there is no single per-site - // bond profile to report: `output_bond_dims` is left empty and the - // size is carried by n_params, n_patches and max_patch_bond. - "output_bond_dims_note": "patched output, see n_params and n_patches", - }); - merge_params(&mut params, &family_params); - let rec = RunRecord { + write_record( + out_dir, + &format!("{CASE}-{arm}-chi{input_chi}"), + &RunRecord { schema_version: SCHEMA_VERSION, case: CASE.into(), algorithm: arm.into(), params, - seed: cfg.seed, - tolerance: rtol, + seed: config.seed, + tolerance: internal_tolerance, wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: patched_input_bond, - output_max_bond_dim: out_bond, - output_bond_dims: Vec::new(), - n_params: Some(n_params), - n_patches: Some(h.len()), - max_patch_bond: Some(out_bond), - rtol: Some(rtol), - input_build_secs: Some(patched_build_secs), - }; - // The family is part of the record name: the two families share their - // arm names, so a sweep of one would otherwise overwrite the records of - // the other in a profile that holds both. - write_record( - &cfg.out_dir, - &format!("{CASE}-{}-{arm}-n{n}", cfg.family.label()), - &rec, - )?; - eprintln!( - " {arm}: t={:.4}s rel_err={max_error:.2e} patches={} bond={out_bond} \ - params={n_params} pairs={} pairs_t={:.3}s truncate_t={:.3}s", - timing.median_secs, - h.len(), - stats.n_pairs, - stats.pairs_secs, - stats.truncate_secs - ); - if !max_error.is_finite() || max_error > cfg.sanity { - failures.push(format!( - "{arm} n={n}: rel err {max_error:.2e} > {:.2e}", - cfg.sanity - )); - } - // A binding cap would mean the arm was truncated by a rank rather than by - // rtol, which would break the equal-accuracy comparison. - if out_bond >= cfg.product_max_bond { - failures.push(format!( - "{arm} n={n}: output patch bond {out_bond} reached the cap \ - BENCH_PATCH_OUT_MAX_BOND={}, so the arm was rank-truncated and is no \ - longer comparable at equal rtol", - cfg.product_max_bond - )); - } - } - - let global_arms: Vec<(&str, ElementwiseAlgo)> = if cfg.baselines { - [ - ( - "fit_treetn", - ElementwiseAlgo::Fit, - cfg.family.max_n_with_fit_baseline(), - ), - ( - "aci", - ElementwiseAlgo::Aci, - cfg.family.max_n_with_aci_baseline(), - ), - ] - .into_iter() - .filter(|&(_, _, max_n)| n <= max_n) - .map(|(arm, algo, _)| (arm, algo)) - .collect() - } else { - Vec::new() - }; - if global_arms.is_empty() { - return Ok(()); - } + wall_times_secs: timing.runs_secs.clone(), + max_error: error, + input_max_bond_dim: input_chi, + output_max_bond_dim: output.rank(), + output_bond_dims: output.link_dims(), + n_params: Some(tt_n_params(output)), + n_patches: None, + max_patch_bond: None, + rtol: (tolerance_metric == "relative_l2_svd").then_some(INPUT_L2_RTOL), + input_build_secs: Some(input.build.as_secs_f64()), + }, + ) +} - // Global baselines at the same rtol, with no binding rank cap: the tolerance - // alone decides where they stop, which is what makes them comparable with the - // patched arms. On the norm path these are the same two trains the patched - // inputs were split out of, so they are reused rather than built a second - // time: an identical construction repeated would cost the sweep a second - // global build without measuring anything the first one did not. - let (fa, gb, global_build_secs) = match global_inputs { - Some(built) => built, - None => { - let t0 = Instant::now(); - let (fa, _step) = to_quantics_fused_tt_field(f, r, box_l, rtol, cfg.global_max_bond)?; - let (gb, _) = to_quantics_fused_tt_field(g, r, box_l, rtol, cfg.global_max_bond)?; - (fa, gb, t0.elapsed().as_secs_f64()) - } - }; - let global_input_bond = fa.rank().max(gb.rank()); - let global_input_params = tt_n_params(&fa) + tt_n_params(&gb); - eprintln!( - " global inputs: chi_in={global_input_bond} params={global_input_params} \ - build={global_build_secs:.3}s" +#[allow(clippy::too_many_arguments)] +fn write_patched_record( + out_dir: &Path, + arm: &str, + input: &t4a_bench::gaussian_input::GaussianInputPair, + config: &GaussianInputConfig, + input_chi: usize, + input_params: usize, + patch_count: usize, + input_max_patch: usize, + patch_params: usize, + patch_secs: f64, + left_input_error: f64, + right_input_error: f64, + internal_tolerance: f64, + tolerance_metric: &str, + output: &tensor4all_partitionedtt::PartitionedTT, + error: f64, + timing: &t4a_bench::harness::Timing, + global_time: f64, + sites: &[tensor4all_core::DynIndex], +) -> anyhow::Result<()> { + let mut params = common_params( + input, + config, + input_params, + patch_count, + input_max_patch, + patch_params, + patch_secs, + left_input_error, + right_input_error, + internal_tolerance, + tolerance_metric, ); - // Already checked above where the norm path built these very trains, so this - // covers the tci path, whose global trains are built only here. - if norm_global_chi.is_none() && global_input_bond >= cfg.global_max_bond { - failures.push(format!( - "n={n}: global input chi {global_input_bond} reached the construction cap \ - BENCH_MAX_BOND={}, so the baseline is cap-limited rather than \ - tolerance-limited", - cfg.global_max_bond - )); - } - for (arm, algo) in global_arms { - let (h, timing) = time_median(cfg.warmups, cfg.runs, || { - elementwise_product( - algo, - &fa, - &gb, - rtol, - cfg.global_max_bond, - AciTolerance::Absolute, - ) - .expect("global product failed") - }); - let max_error = - max_rel_error_vs_product(&h, f, g, r, box_l, cfg.n_error_samples, cfg.error_seed); - let n_params = tt_n_params(&h); - let mut params = serde_json::json!({ - "n_gauss": n, "box_l": box_l, "r": r, - "family": cfg.family.label(), - "arm_kind": "global", - // Which construction the instance ran, as on the patched arms: on the - // norm path this arm runs on the very trains the patches were split - // out of, so its input_build_secs is a part of theirs, while on the - // tci path it builds the only global trains of the point. - "input_path": cfg.input_path.label(), - "max_bond": cfg.global_max_bond, - "contract_max_bond": cfg.global_max_bond, - "contract_tol": rtol, - // The aci arm runs on an absolute pivot budget, not on the upstream - // default scale-relative one. This case measures a GLOBAL relative - // error, normalized by the largest sampled |f g| of the whole box, - // and BENCH_RTOL times the sampled scale of the function is exactly - // that budget. The upstream scale-relative criterion normalizes each - // bond by its own largest sampled output instead, which is the - // per-region relative tolerance this case deliberately refuses - // everywhere else (see the tolerance handling of the patched inputs). - // Measured, it is not a cosmetic difference: on the smooth family at - // N = 32 the same arm at the same pin returns chi_out = 138, 147972 - // parameters and 8.4e-9 with an absolute budget, against chi_out = 473 - // capped at BENCH_MAX_BOND, 1.7e6 parameters and 2.7e-1 with the - // scale-relative one, which fails the sanity gate. - "aci_tolerance": "absolute", - "aci_scale_tolerance": false, - "input_n_params": global_input_params, - "runs": cfg.runs, "warmups": cfg.warmups, - "n_error_samples": cfg.n_error_samples, "error_seed": cfg.error_seed, - "error_metric": "max_rel_vs_analytic", - "ref_scale": scales.ref_scale, - "input_scale_f": scales.input_scale_f, - "input_scale_g": scales.input_scale_g, - "engine": algo.engine(), - "fit_nsweeps": FIT_NFULLSWEEPS, - }); - merge_params(&mut params, &family_params); - let rec = RunRecord { + params["speedup_vs_global"] = serde_json::json!(global_time / timing.median_secs); + write_record( + out_dir, + &format!("{CASE}-{arm}-chi{input_chi}"), + &RunRecord { schema_version: SCHEMA_VERSION, case: CASE.into(), algorithm: arm.into(), params, - seed: cfg.seed, - tolerance: rtol, + seed: config.seed, + tolerance: internal_tolerance, wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: global_input_bond, - output_max_bond_dim: h.rank(), - output_bond_dims: h.link_dims(), - n_params: Some(n_params), - n_patches: None, - max_patch_bond: None, - rtol: Some(rtol), - input_build_secs: Some(global_build_secs), - }; - // The family is part of the record name: the two families share their - // arm names, so a sweep of one would otherwise overwrite the records of - // the other in a profile that holds both. - write_record( - &cfg.out_dir, - &format!("{CASE}-{}-{arm}-n{n}", cfg.family.label()), - &rec, - )?; - eprintln!( - " {arm}: t={:.4}s rel_err={max_error:.2e} chi_out={} params={n_params}", - timing.median_secs, - h.rank() - ); - if !max_error.is_finite() || max_error > cfg.sanity { - failures.push(format!( - "{arm} n={n}: rel err {max_error:.2e} > {:.2e}", - cfg.sanity - )); - } - // The same check the patched arms get, and for the same reason: a global - // baseline that ran into its rank cap was truncated by a rank rather than - // by rtol, so it is no longer the tolerance-driven object this case puts - // next to the patched arms at equal accuracy. It is a separate failure - // from the error gate, since a cap-limited arm can still land under the - // gate while measuring the cap. - if h.rank() >= cfg.global_max_bond { - failures.push(format!( - "{arm} n={n}: output chi {} reached the cap BENCH_MAX_BOND={}, so the \ - baseline was rank-truncated and is no longer comparable at equal rtol", - h.rank(), - cfg.global_max_bond - )); - } - } - Ok(()) -} - -/// Fold the family-specific params into a record's params object. -fn merge_params(into: &mut serde_json::Value, extra: &serde_json::Value) { - let (Some(target), Some(source)) = (into.as_object_mut(), extra.as_object()) else { - panic!("params of a record have to be JSON objects"); - }; - for (key, value) in source { - target.insert(key.clone(), value.clone()); - } -} - -#[cfg(test)] -mod tests { - use super::{aniso_box_and_bits, box_and_bits, Family}; - - /// The smooth instance family has to stay case 4's, or the two cases would not - /// be measuring the same problem at two different controls. - #[test] - fn box_and_bits_matches_case_four() { - let (l0, n0, r0) = (6.0, 8, 10); - for &n in &[8usize, 16, 32, 64, 128, 256] { - let (l, r) = box_and_bits(n, n0, l0, r0); - let expected_l = l0 * (n as f64 / n0 as f64).sqrt(); - assert!((l - expected_l).abs() < 1e-12); - assert_eq!(r, (r0 as f64 + (l / l0).log2().round()) as usize); - // Area per Gaussian is exactly constant, by construction. - let area_per = (2.0 * l).powi(2) / n as f64; - assert!((area_per / ((2.0 * l0).powi(2) / n0 as f64) - 1.0).abs() < 1e-12); - } - assert_eq!(box_and_bits(8, 8, 6.0, 10), (6.0, 10)); - } - - /// The aniso family holds the spacing-to-width ratio fixed and resolves the - /// minor width to a quarter of a grid step, which are the two properties its - /// non degenerate product and its meaningful error metric rest on. - #[test] - fn aniso_box_and_bits_holds_spacing_and_resolution() { - let (sigma, spacing) = (0.05, 3.0); - for &n in &[8usize, 64, 128, 256, 1024, 2048] { - let (l, r) = aniso_box_and_bits(n, sigma, spacing); - // Mean spacing, box side over sqrt(N), is exactly spacing * sigma. - let mean_spacing = 2.0 * l / (n as f64).sqrt(); - assert!((mean_spacing - spacing * sigma).abs() < 1e-12, "n={n}"); - let step = 2.0 * l / (1u64 << r) as f64; - assert!(step <= sigma / 4.0, "n={n}: step {step} too coarse"); - // And R is the smallest such bit count, so the grid is not oversized. - let coarser = 2.0 * l / (1u64 << (r - 1)) as f64; - assert!(coarser > sigma / 4.0, "n={n}: R={r} is larger than needed"); - } - // The measured chi table of the README quotes R = 9 at N = 1024, where the - // global rank reaches the geometric bound, and R = 10 at 2048. - assert_eq!(aniso_box_and_bits(1024, 0.05, 3.0).1, 9); - assert_eq!(aniso_box_and_bits(2048, 0.05, 3.0).1, 10); - } - - #[test] - fn family_parses_both_names_and_nothing_else() { - assert_eq!(Family::parse("aniso"), Some(Family::Aniso)); - assert_eq!(Family::parse("smooth"), Some(Family::Smooth)); - assert_eq!(Family::parse("gaussian"), None); - } + wall_times_secs: timing.runs_secs.clone(), + max_error: error, + input_max_bond_dim: input_chi, + output_max_bond_dim: max_patch_bond(output), + output_bond_dims: output.values().map(|patch| patch.max_bond_dim()).collect(), + n_params: Some(total_params(output, sites)?), + n_patches: Some(output.len()), + max_patch_bond: Some(max_patch_bond(output)), + rtol: Some(INPUT_L2_RTOL), + input_build_secs: Some(input.build.as_secs_f64()), + }, + ) } diff --git a/src/bin/elementwise_gauss2d_scaling.rs b/src/bin/elementwise_gauss2d_scaling.rs deleted file mode 100644 index c2e4055..0000000 --- a/src/bin/elementwise_gauss2d_scaling.rs +++ /dev/null @@ -1,362 +0,0 @@ -//! Case 4 runner: density-constant scaling study of case 3. -//! -//! Case 3 sweeps the bit count `R` at a fixed mixture and watches the quantics -//! rank saturate. This case asks the complementary question: how does the input -//! rank `chi_in` of a 2D Gaussian mixture grow with the number of Gaussians `N` -//! when the DENSITY of Gaussians is held constant? The two hypotheses worth -//! separating are `chi ~ sqrt(N)`, which is what a boundary-law or -//! one-dimensional-cut picture predicts for a fused 2D quantics train, and -//! `chi ~ N`, which is what a naive sum-of-terms picture predicts. -//! -//! Density-constant construction. For each `N` in `BENCH_NS` the box half-width -//! grows as -//! -//! ```text -//! L = L0 * sqrt(N / N0) -//! ``` -//! -//! so the box area `(2L)^2` grows proportionally to `N` and the number of -//! Gaussians per unit area is the same at every point of the sweep. Growing the -//! box while keeping `R` fixed would coarsen the grid and under-resolve each -//! Gaussian, which would confound rank growth with a loss of resolution, so the -//! bit count grows with the box: -//! -//! ```text -//! R = R0 + round(log2(L / L0)) -//! ``` -//! -//! that is, one extra bit per doubling of the box, which keeps the grid spacing -//! `2L / 2^R` roughly constant, so every Gaussian is resolved by roughly the -//! same number of grid points at every `N`. The rounding means `R` moves in -//! integer steps while `L` moves continuously, so the spacing is only constant -//! up to a factor of at most `sqrt(2)`. -//! -//! Everything else mirrors case 3: two independent mixtures from -//! `GaussianMixture2D::random` at seeds `seed + 1` and `seed + 2`, fused 2D -//! quantics trains via `to_quantics_fused_tt`, and the elementwise product -//! `h = f * g` at the fixed output budget `chi_out <= chi_in`, judged by the -//! sampled max relative error against the exact pointwise product. -//! -//! As in cases 2 and 3, that budget is decided by the rank cap alone. -//! `BENCH_TOL` (default 1e-8) scopes only the input TCI construction, so it -//! defines `chi_in` and the instance, while `BENCH_CONTRACT_TOL` (default 1e-15) -//! is the truncation tolerance every arm receives and is recorded as -//! `contract_tol`. At 1e-15 it never fires, so the arms exhaust the budget unless -//! their exact rank is smaller. The `aci` arm additionally runs with -//! `scale_tolerance` enabled (`AciTolerance::ScaleRelative`, recorded as -//! `aci_scale_tolerance`) so that its pivot criterion is scale-relative and -//! equally unreachable; the pinned rev includes the rank-saturation early exit of -//! tensor4all-rs#591, so a capped ACI stops once its pivots stop improving instead -//! of running to `max_iters`, and the arm is the cheapest of the three. -//! -//! Arms: `zipup_treetn`, `fit_treetn` and `aci` only. The `naive` arm of case 3 -//! is excluded here: it forms the full `chi_in`-squared bond before truncating, -//! and this case deliberately pushes `chi_in` to roughly twice the case-3 value, -//! where that arm dominates the wall time of the whole sweep without adding a -//! separate conclusion (it tracks `fit_treetn` to the last reported digit in -//! case 3). Run it explicitly through `BENCH_ALGOS` if you want it. -//! -//! As in case 3, `zipup_treetn` is expected to return an order-one relative -//! error at this budget and is gated only against a scale blow-up. - -use std::path::PathBuf; -use t4a_bench::elementwise::{ - check_mixture_product_not_degenerate, elementwise_product, max_rel_error_vs_mixture_product, - tt_n_params, AciTolerance, ElementwiseAlgo, FIT_NFULLSWEEPS, -}; -use t4a_bench::gaussian::{to_quantics_fused_tt, GaussianMixture2D}; -use t4a_bench::harness::time_median; -use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; -use tensor4all_simplett::AbstractTensorTrain; - -const CASE: &str = "elementwise_gauss2d_scaling"; - -/// Sanity gate for the `zipup_treetn` arm, which cannot share `BENCH_SANITY`. -/// -/// Same reasoning as case 3: at an output budget of `chi_in` the single-pass -/// zip-up truncation of an elementwise product returns a relative error of -/// order one, so a gate that screens order-unity wrongness has nothing to grip. -/// This arm is therefore gated only against a gross scale blow-up or a -/// non-finite result. -const ZIPUP_SANITY: f64 = 5.0; - -fn env_or(key: &str, default: T) -> T { - std::env::var(key) - .ok() - .and_then(|v| v.parse().ok()) - .unwrap_or(default) -} - -fn parse_algo(s: &str) -> ElementwiseAlgo { - match s { - "naive" => ElementwiseAlgo::Naive, - "zipup_treetn" => ElementwiseAlgo::Zipup, - "fit_treetn" => ElementwiseAlgo::Fit, - "aci" => ElementwiseAlgo::Aci, - other => panic!("unknown algorithm {other}"), - } -} - -/// Box half-width and bit count for `n` Gaussians at constant density. -/// -/// `L` grows like `sqrt(N)` so the area grows like `N`, and `R` gains one bit -/// per doubling of `L` so the grid spacing stays roughly constant. Exposed as a -/// function so the test and the runner cannot drift apart. -pub fn box_and_bits(n: usize, n0: usize, l0: f64, r0: usize) -> (f64, usize) { - let l = l0 * (n as f64 / n0 as f64).sqrt(); - let r = r0 as f64 + (l / l0).log2().round(); - (l, r.max(1.0) as usize) -} - -fn main() -> anyhow::Result<()> { - let ns: Vec = std::env::var("BENCH_NS") - .unwrap_or_else(|_| "8,16,32,64".into()) - .split(',') - .map(|s| s.trim().parse().unwrap()) - .collect(); - let l0: f64 = env_or("BENCH_L0", 6.0); - let n0: usize = env_or("BENCH_N0", 8); - let r0: usize = env_or("BENCH_R0", 10); - let alpha_lo: f64 = env_or("BENCH_ALPHA_LO", 0.5); - let alpha_hi: f64 = env_or("BENCH_ALPHA_HI", 8.0); - // Instance tolerance: this defines chi_in through the input TCI, and nothing - // else. It is what `RunRecord::tolerance` reports, since that describes the - // inputs rather than the product. - let tol: f64 = env_or("BENCH_TOL", 1e-8); - // Product tolerance, pinned inert so the rank cap chi_in is the only binding - // truncation control for every arm. - let contract_tol: f64 = env_or("BENCH_CONTRACT_TOL", 1e-15); - let max_bond: usize = env_or("BENCH_MAX_BOND", 512); - let runs: usize = env_or("BENCH_RUNS", 3); - let warmups: usize = env_or("BENCH_WARMUPS", 0); - let seed: u64 = env_or("BENCH_SEED", 0); - // As in case 3, the output budget is fixed at chi_in, so truncation error is - // the quantity being measured and the gate only screens order-unity - // wrongness. - let sanity: f64 = env_or("BENCH_SANITY", 1e-2); - let algos: Vec = std::env::var("BENCH_ALGOS") - .unwrap_or_else(|_| "zipup_treetn,fit_treetn,aci".into()) - .split(',') - .map(|s| s.trim().to_string()) - .collect(); - let out_dir = - PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); - - // Accuracy check sampling, recorded in every record's params. - let n_error_samples: usize = 128; - let error_seed: u64 = seed.wrapping_add(99); - - let mut failures = Vec::new(); - for &n in &ns { - let (box_l, r) = box_and_bits(n, n0, l0, r0); - let f = GaussianMixture2D::random(n, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(1)); - let g = GaussianMixture2D::random(n, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(2)); - - let (fa, _step) = to_quantics_fused_tt(&f, r, box_l, tol, max_bond)?; - let (gb, _) = to_quantics_fused_tt(&g, r, box_l, tol, max_bond)?; - let input_chi = fa.rank().max(gb.rank()); - // Fail fast, before any timing: at constant density the box grows with - // N, so this is where too narrow a Gaussian would empty the product. - let scales = - check_mixture_product_not_degenerate(&f, &g, r, box_l, n_error_samples, error_seed)?; - eprintln!( - "n={n} box_l={box_l:.3} r={r} input_chi={input_chi} ref_scale={:.3e}", - scales.ref_scale - ); - // The point of the case is how chi_in grows, so a chi_in pinned at the - // construction cap would be a measurement of the cap instead. - if input_chi >= max_bond { - failures.push(format!( - "n={n}: input chi {input_chi} reached the construction cap \ - BENCH_MAX_BOND={max_bond}, so the measured rank is the cap, \ - not the rank of the function" - )); - } - - for algo_name in &algos { - let algo = parse_algo(algo_name); - let (h, timing) = time_median(warmups, runs, || { - elementwise_product( - algo, - &fa, - &gb, - contract_tol, - input_chi, - AciTolerance::ScaleRelative, - ) - .expect("product failed") - }); - let max_error = - max_rel_error_vs_mixture_product(&h, &f, &g, r, box_l, n_error_samples, error_seed); - let rec = RunRecord { - schema_version: SCHEMA_VERSION, - case: CASE.into(), - algorithm: algo_name.clone(), - params: serde_json::json!({ - "n_gauss": n, "box_l": box_l, "r": r, - "l0": l0, "n0": n0, "r0": r0, - "alpha_range": [alpha_lo, alpha_hi], "max_bond": max_bond, - // Output budget shared by every algorithm: the input rank. - "contract_max_bond": input_chi, - // Truncation tolerance the arms actually ran with, pinned - // inert so the cap above is what decides. The top-level - // `tolerance` field is the instance tolerance instead. - "contract_tol": contract_tol, - // True on the aci arm, whose stopping criterion is then - // scale-relative, so the inert tolerance above is - // unreachable for it too. The other arms are SVD-based and - // have no such switch. - "aci_scale_tolerance": matches!(algo, ElementwiseAlgo::Aci), - "runs": runs, "warmups": warmups, - "n_error_samples": n_error_samples, "error_seed": error_seed, - "error_metric": "max_rel_vs_analytic", - // Scales of the reference and of the two inputs at the same - // sampled points, so a degenerate instance is visible in the - // record rather than hidden inside the relative error. - "ref_scale": scales.ref_scale, - "input_scale_f": scales.input_scale_f, - "input_scale_g": scales.input_scale_g, - // Upstream engine that actually ran this arm. - "engine": algo.engine(), - // Part of the benchmark definition for the fit arm. - "fit_nsweeps": FIT_NFULLSWEEPS, - }), - seed, - tolerance: tol, - wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: h.rank(), - output_bond_dims: h.link_dims(), - n_params: Some(tt_n_params(&h)), - n_patches: None, - max_patch_bond: None, - rtol: None, - input_build_secs: None, - }; - write_record(&out_dir, &format!("{CASE}-{algo_name}-n{n}"), &rec)?; - eprintln!( - " {algo_name}: t={:.4}s rel_err={max_error:.2e} chi_out={}", - timing.median_secs, - h.rank() - ); - let gate = if matches!(algo, ElementwiseAlgo::Zipup) { - ZIPUP_SANITY - } else { - sanity - }; - if !max_error.is_finite() || max_error > gate { - failures.push(format!( - "{algo_name} n={n}: rel err {max_error:.2e} > {gate:.2e}" - )); - } - } - } - if !failures.is_empty() { - anyhow::bail!("sanity failures:\n{}", failures.join("\n")); - } - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::{box_and_bits, ZIPUP_SANITY}; - use t4a_bench::elementwise::{ - elementwise_product, max_rel_error_vs_mixture_product, AciTolerance, ElementwiseAlgo, - }; - use t4a_bench::gaussian::{to_quantics_fused_tt, GaussianMixture2D}; - use tensor4all_simplett::AbstractTensorTrain; - - /// The density-constant construction: area proportional to N, grid spacing - /// constant up to the integer rounding of R. - #[test] - fn box_and_bits_hold_density_and_resolution() { - let (l0, n0, r0) = (6.0, 8, 10); - let (l8, r8) = box_and_bits(8, n0, l0, r0); - assert!((l8 - 6.0).abs() < 1e-12); - assert_eq!(r8, 10); - // Area per Gaussian is exactly constant, by construction. - for &n in &[8usize, 16, 32, 64, 128] { - let (l, r) = box_and_bits(n, n0, l0, r0); - let area_per = (2.0 * l).powi(2) / n as f64; - let area_per0 = (2.0 * l8).powi(2) / 8.0; - assert!( - (area_per / area_per0 - 1.0).abs() < 1e-12, - "n={n}: density drifted" - ); - // Grid spacing constant to within the sqrt(2) the rounding allows. - let step = 2.0 * l / (1u64 << r) as f64; - let step0 = 2.0 * l8 / (1u64 << r8) as f64; - let ratio: f64 = step / step0; - assert!( - ratio > 0.7 && ratio < 1.42, - "n={n}: grid spacing ratio {ratio} outside the rounding band" - ); - } - } - - /// The smallest point of the default sweep, at a reduced `R0` to keep the - /// test cheap: the three default arms must build, honour the fixed output - /// budget and land inside the gates the runner would apply to them. - /// - /// The bounds are the runner's own: `BENCH_SANITY` (1e-2) for `fit_treetn` - /// and `aci`, and the hardcoded `ZIPUP_SANITY` for `zipup_treetn`, whose - /// error at this budget is genuinely of order one (README known issue 8). - /// The tolerance handed to the arms is the runner's inert 1e-15 and the aci - /// arm runs scale-relative, so the cap is what decides and the SVD-based arms - /// are expected to spend the whole budget. Measured at the pinned revision on - /// this instance (chi_in 76): zipup 1.8e-1, fit 6.7e-9 and aci 6.7e-9, all at - /// chi_out 76. - /// This is a smoke test of the case-4 wiring, not a precision claim: the - /// scaling answer comes from the runner, not from here. - #[test] - fn scaling_arms_meet_their_gates_at_the_smallest_point() { - let (l, r) = box_and_bits(8, 8, 6.0, 8); - assert_eq!((l, r), (6.0, 8)); - let f = GaussianMixture2D::random(8, l, (0.5, 8.0), 1); - let g = GaussianMixture2D::random(8, l, (0.5, 8.0), 2); - let (fa, _) = to_quantics_fused_tt(&f, r, l, 1e-8, 512).unwrap(); - let (gb, _) = to_quantics_fused_tt(&g, r, l, 1e-8, 512).unwrap(); - let chi_in = fa.rank().max(gb.rank()); - - // The third element says whether the arm is expected to spend the whole - // budget. The two SVD-based arms keep everything the cap allows, since the - // tolerance can no longer stop them; aci is interpolation-based and may - // settle below the cap, so it is only held to the cap as an upper bound. - for (algo, bound, exhausts_budget) in [ - (ElementwiseAlgo::Zipup, ZIPUP_SANITY, true), - (ElementwiseAlgo::Fit, 1e-2, true), - (ElementwiseAlgo::Aci, 1e-2, false), - ] { - // The budget is the cap, so the tolerance is pinned inert, exactly as - // the runner does it. - let out = - elementwise_product(algo, &fa, &gb, 1e-15, chi_in, AciTolerance::ScaleRelative) - .unwrap(); - assert!( - out.rank() <= chi_in, - "{algo:?}: chi_out {} exceeds the budget {chi_in}", - out.rank() - ); - if exhausts_budget { - assert_eq!( - out.rank(), - chi_in, - "{algo:?}: chi_out {} fell short of the budget {chi_in}, so something \ - other than the cap truncated it", - out.rank() - ); - } - let err = max_rel_error_vs_mixture_product(&out, &f, &g, r, l, 128, 99); - println!( - "{algo:?}: rel err {err:.3e} (bound {bound:.0e}), chi_out {} of {chi_in}", - out.rank() - ); - assert!( - err.is_finite() && err < bound, - "{algo:?}: rel err {err} exceeds {bound}" - ); - } - } -} diff --git a/src/bin/mpo_mpo_aniso_patched.rs b/src/bin/mpo_mpo_aniso_patched.rs index 15431a8..86ba0b9 100644 --- a/src/bin/mpo_mpo_aniso_patched.rs +++ b/src/bin/mpo_mpo_aniso_patched.rs @@ -1,579 +1,250 @@ -//! Global and patched chain-TreeTN fit contraction of anisotropic Gaussian MPOs. +//! Case 3: global and patched fit contraction of interpolative Gaussian MPOs. -use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::Instant; -use tensor4all_hdf5::{append_mps, load_mps, save_mps}; use tensor4all_itensorlike::TensorTrain; -use tensor4all_simplett::mpo::MPO; +use tensor4all_simplett::AbstractTensorTrain; -use t4a_bench::gaussian::{ - grid_coord, to_quantics_mpo_field_with_pivots, AnisoMixture2D, Field2D, LocalizedAnisoField, -}; -use t4a_bench::harness::{index_to_bits, sample_grid_indices, time_median}; -use t4a_bench::mpo_contract::{max_rel_error_vs_aniso_grid, mpo_n_params, tensortrain_to_mpo}; -use t4a_bench::patched_mpo::{ - mpo_pair_to_tensortrains, tensortrain_n_params, truncate_tensortrain_l2, PatchedMpoOutput, - PatchedMpoPair, +use t4a_bench::gaussian::fused_qtt_to_mpo; +use t4a_bench::gaussian_input::{ + prepare_gaussian_pair, sampled_input_relative_l2, tensortrain_n_params as simple_n_params, + GaussianInputConfig, INPUT_L2_RTOL, PATCH_CAP, }; +use t4a_bench::harness::time_median; +use t4a_bench::mpo_contract::sampled_relative_l2_vs_aniso_grid; +use t4a_bench::patched_mpo::{partitioned_treetn_n_params, tensortrain_n_params, PatchedMpoPair}; use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; -fn env_or(key: &str, default: T) -> T { - std::env::var(key) +const CASE: &str = "gaussian_mpo_contraction"; +const GLOBAL_MAX_BOND: usize = 4096; +const ERROR_SAMPLES: usize = 256; +const ERROR_SANITY: f64 = 1e-4; + +fn env_or(name: &str, default: T) -> T { + std::env::var(name) .ok() .and_then(|value| value.parse().ok()) .unwrap_or(default) } -fn tensortrain_pair_to_mpos( - left: &TensorTrain, - right: &TensorTrain, -) -> anyhow::Result<(MPO, MPO)> { - let left_sites = left.site_indices(); - let right_sites = right.site_indices(); - let mut x = Vec::with_capacity(left.len()); - let mut y = Vec::with_capacity(left.len()); - let mut z = Vec::with_capacity(left.len()); - for site in 0..left.len() { - let common = left_sites[site] - .iter() - .find(|index| right_sites[site].contains(index)) - .ok_or_else(|| anyhow::anyhow!("input site {site} has no shared index"))?; - let left_unique = left_sites[site] - .iter() - .find(|index| *index != common) - .ok_or_else(|| anyhow::anyhow!("left input site {site} has no unique index"))?; - let right_unique = right_sites[site] - .iter() - .find(|index| *index != common) - .ok_or_else(|| anyhow::anyhow!("right input site {site} has no unique index"))?; - x.push(left_unique.clone()); - y.push(common.clone()); - z.push(right_unique.clone()); - } - Ok(( - tensortrain_to_mpo(left, &x, &y)?, - tensortrain_to_mpo(right, &y, &z)?, - )) -} - -fn max_rel_input_error( - mpo: &MPO, - field: &impl Field2D, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> anyhow::Result { - let xs = sample_grid_indices(r, n_samples, seed); - let ys = sample_grid_indices(r, n_samples, seed.wrapping_add(1)); - let mut max_error = 0.0_f64; - let mut max_reference = 0.0_f64; - for (&ix, &iy) in xs.iter().zip(&ys) { - let x = grid_coord(ix, r, box_l); - let y = grid_coord(iy, r, box_l); - let indices = index_to_bits(ix, r) - .into_iter() - .zip(index_to_bits(iy, r)) - .flat_map(|(x_bit, y_bit)| [x_bit, y_bit]) - .collect::>(); - let reference = field.eval(x, y); - let value = mpo.evaluate(&indices)?; - max_error = max_error.max((value - reference).abs()); - max_reference = max_reference.max(reference.abs()); - } - Ok(max_error / max_reference.max(f64::MIN_POSITIVE)) -} - -fn center_grid_pivots( - mixture: &AnisoMixture2D, - count: usize, - r: usize, - box_l: f64, -) -> Vec> { - let grid_size = 1usize << r; - (0..count.min(mixture.centers.len())) - .map(|pivot| { - let component = pivot * mixture.centers.len() / count.min(mixture.centers.len()); - let (x, y) = mixture.centers[component]; - [x, y] - .into_iter() - .map(|coordinate| { - ((coordinate + box_l) * grid_size as f64 / (2.0 * box_l)).floor() as usize - }) - .map(|index| index.min(grid_size - 1)) - .collect() - }) - .collect() -} - fn main() -> anyhow::Result<()> { - let n_gauss: usize = env_or("BENCH_NGAUSS", 512); - let sigma: f64 = env_or("BENCH_ANISO_SIGMA", 0.05); - let rho_max: f64 = env_or("BENCH_ANISO_RHO_MAX", 8.0); - let spacing: f64 = env_or("BENCH_ANISO_SPACING", 3.0); - let box_padding: f64 = env_or("BENCH_BOX_PADDING", 1.0); - let extra_bits: usize = env_or("BENCH_R_EXTRA", 0); - let rtol: f64 = env_or("BENCH_RTOL", 1e-8); - let input_generator = std::env::var("BENCH_INPUT_GENERATOR").unwrap_or_else(|_| "tci".into()); - let input_tci_rtol: f64 = env_or("BENCH_INPUT_TCI_RTOL", 1e-8); - let input_poly_degree: usize = env_or("BENCH_INPUT_POLY_DEGREE", 28); - let input_add_rtol: f64 = env_or("BENCH_INPUT_ADD_RTOL", 1e-10); - let input_tci_local_abs_tol: f64 = env_or("BENCH_TCI_LOCAL_ABS_TOL", 1e-12); - let input_tci_initial_pivots: usize = env_or("BENCH_TCI_INITIAL_PIVOTS", 8); - let input_svd_l2_rtol: f64 = env_or("BENCH_INPUT_SVD_RTOL", 1e-6); - let input_only = std::env::var_os("BENCH_INPUT_ONLY").is_some(); - let input_tci_cap: usize = env_or("BENCH_MAX_BOND", 384); - let patch_cap: usize = env_or("BENCH_PATCH_MAX_BOND", 128); - let max_input_chi: usize = env_or("BENCH_MAX_INPUT_CHI", 256); - let runs: usize = env_or("BENCH_RUNS", 1); - let warmups: usize = env_or("BENCH_WARMUPS", 0); - let seed: u64 = env_or("BENCH_SEED", 0); - let sanity: f64 = env_or("BENCH_SANITY", 1e-4); - let input_sanity: f64 = env_or("BENCH_INPUT_SANITY", 1e-4); - let n_error_samples: usize = env_or("BENCH_ERROR_SAMPLES", 128); + let ns = std::env::var("BENCH_NS").unwrap_or_else(|_| "2,8,32,128".into()); + let ns = ns + .split(',') + .map(|value| value.trim().parse::().map_err(anyhow::Error::from)) + .collect::>>()?; let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); let cache_dir = PathBuf::from( std::env::var("BENCH_INPUT_CACHE_DIR").unwrap_or_else(|_| ".cache/inputs".into()), ); - let refresh_cache = std::env::var_os("BENCH_INPUT_CACHE_REFRESH").is_some(); - - anyhow::ensure!(n_gauss > 0 && sigma > 0.0 && spacing > 0.0); - anyhow::ensure!(box_padding >= 1.0 && rho_max >= 1.0); - anyhow::ensure!(rtol.is_finite() && rtol >= 0.0); - anyhow::ensure!(input_generator == "tci" || input_generator == "multiscale"); - anyhow::ensure!(input_tci_rtol.is_finite() && input_tci_rtol >= 0.0); - anyhow::ensure!(input_poly_degree >= 2); - anyhow::ensure!(input_add_rtol.is_finite() && input_add_rtol >= 0.0); - anyhow::ensure!(input_tci_local_abs_tol.is_finite() && input_tci_local_abs_tol > 0.0); - anyhow::ensure!(input_tci_initial_pivots > 0); - anyhow::ensure!(input_svd_l2_rtol.is_finite() && input_svd_l2_rtol >= 0.0); - anyhow::ensure!(input_tci_cap > 0 && patch_cap > 0 && runs > 0); - - // Same constant-density anisotropic family and resolution as case 5. - let inner_l = spacing * sigma * (n_gauss as f64).sqrt() / 2.0; - let box_l = box_padding * inner_l; - let r = (8.0 * box_l / sigma).log2().ceil().max(1.0) as usize + extra_bits; - let f = AnisoMixture2D::random(n_gauss, inner_l, sigma, rho_max, seed.wrapping_add(1)); - let g = AnisoMixture2D::random(n_gauss, inner_l, sigma, rho_max, seed.wrapping_add(2)); + let refresh = env_or("BENCH_INPUT_CACHE_REFRESH", 0usize) != 0; + let runs = env_or("BENCH_RUNS", 1usize); + let warmups = env_or("BENCH_WARMUPS", 0usize); + let seed = env_or("BENCH_SEED", 0u64); + for n in ns { + run_point(n, seed, runs, warmups, &cache_dir, refresh, &out_dir)?; + } + Ok(()) +} - fs::create_dir_all(&cache_dir)?; - let cache_key = if input_generator == "tci" { - format!( - "aniso-v5-tci-n{n_gauss}-r{r}-e{extra_bits}-s{:x}-p{:x}-sig{:x}-rho{:x}-tol{:x}-loc{:x}-piv{input_tci_initial_pivots}-cap{input_tci_cap}-seed{seed}", - spacing.to_bits(), - box_padding.to_bits(), - sigma.to_bits(), - rho_max.to_bits(), - input_tci_rtol.to_bits(), - input_tci_local_abs_tol.to_bits(), - ) - } else { - format!( - "aniso-v4-ms-n{n_gauss}-r{r}-e{extra_bits}-s{:x}-p{:x}-sig{:x}-rho{:x}-tol{:x}-d{input_poly_degree}-add{:x}-seed{seed}", - spacing.to_bits(), - box_padding.to_bits(), - sigma.to_bits(), - rho_max.to_bits(), - input_tci_rtol.to_bits(), - input_add_rtol.to_bits(), - ) - }; - let cache_path = cache_dir.join(format!("{cache_key}.h5")); - let dy = 2.0 * box_l / 2.0_f64.powi(r as i32); - let build_started = Instant::now(); - let cache_hit = cache_path.is_file() && !refresh_cache; - let (mut left_train, mut right_train, input_cache_load_secs) = if cache_hit { - eprintln!("loading cached input {}", cache_path.display()); - let load_started = Instant::now(); - let path = cache_path.to_string_lossy(); - let left = load_mps(&path, "left")?; - let right = load_mps(&path, "right")?; - (left, right, load_started.elapsed().as_secs_f64()) - } else { - eprintln!( - "building generator={input_generator} N={n_gauss} R={r} box_l={box_l:.6} input_rtol={input_tci_rtol:.1e} input_tci_cap={input_tci_cap}" - ); - let (left, right) = if input_generator == "tci" { - let localized_f = LocalizedAnisoField::new(f.clone(), input_tci_local_abs_tol)?; - let localized_g = LocalizedAnisoField::new(g.clone(), input_tci_local_abs_tol)?; - let (left, generated_dy) = to_quantics_mpo_field_with_pivots( - &localized_f, - r, - box_l, - input_tci_rtol, - input_tci_cap, - center_grid_pivots(&f, input_tci_initial_pivots, r, box_l), - )?; - let (right, _) = to_quantics_mpo_field_with_pivots( - &localized_g, - r, - box_l, - input_tci_rtol, - input_tci_cap, - center_grid_pivots(&g, input_tci_initial_pivots, r, box_l), - )?; - anyhow::ensure!((generated_dy - dy).abs() <= f64::EPSILON * dy.abs().max(1.0)); - (left, right) - } else { - ( - f.to_multiscale_mpo(r, box_l, input_poly_degree, input_tci_rtol, input_add_rtol)?, - g.to_multiscale_mpo(r, box_l, input_poly_degree, input_tci_rtol, input_add_rtol)?, - ) - }; - let (left_train, right_train) = mpo_pair_to_tensortrains(&left, &right)?; - let temporary = cache_dir.join(format!(".{cache_key}.{}.tmp", std::process::id())); - let temporary_path = temporary.to_string_lossy(); - let write_result = (|| -> anyhow::Result<()> { - save_mps(&temporary_path, "left", &left_train)?; - append_mps(&temporary_path, "right", &right_train)?; - fs::rename(&temporary, &cache_path)?; - Ok(()) - })(); - if write_result.is_err() { - let _ = fs::remove_file(&temporary); - } - write_result?; - (left_train, right_train, 0.0) +#[allow(clippy::too_many_arguments)] +fn run_point( + n: usize, + seed: u64, + runs: usize, + warmups: usize, + cache_dir: &Path, + refresh: bool, + out_dir: &Path, +) -> anyhow::Result<()> { + let config = GaussianInputConfig { + n, + sigma_minor: 0.05, + rho_max: 8.0, + spacing: 3.0, + polynomial_degree: 28, + interpolation_tolerance: 1e-10, + addition_tolerance: 1e-10, + seed, + cache_dir: cache_dir.to_path_buf(), + refresh, }; + let input = prepare_gaussian_pair(&config)?; + let (left_input_error, right_input_error) = + sampled_input_relative_l2(&input, ERROR_SAMPLES, seed.wrapping_add(41))?; anyhow::ensure!( - left_train.len() == r && right_train.len() == r, - "cached input length does not match R={r}" - ); - let raw_input_chi = left_train.max_bond_dim().max(right_train.max_bond_dim()); - let raw_input_params = ( - tensortrain_n_params(&left_train), - tensortrain_n_params(&right_train), - ); - let compression_started = Instant::now(); - truncate_tensortrain_l2(&mut left_train, input_svd_l2_rtol)?; - truncate_tensortrain_l2(&mut right_train, input_svd_l2_rtol)?; - let input_compression_secs = compression_started.elapsed().as_secs_f64(); - let input_chi = left_train.max_bond_dim().max(right_train.max_bond_dim()); - anyhow::ensure!( - input_chi <= max_input_chi, - "compressed input chi {input_chi} exceeds BENCH_MAX_INPUT_CHI={max_input_chi}" - ); - let input_params = ( - tensortrain_n_params(&left_train), - tensortrain_n_params(&right_train), - ); - let (left_mpo, right_mpo) = tensortrain_pair_to_mpos(&left_train, &right_train)?; - let input_errors = ( - max_rel_input_error( - &left_mpo, - &f, - r, - box_l, - n_error_samples, - seed.wrapping_add(11), - )?, - max_rel_input_error( - &right_mpo, - &g, - r, - box_l, - n_error_samples, - seed.wrapping_add(12), - )?, + left_input_error <= ERROR_SANITY && right_input_error <= ERROR_SANITY, + "input error exceeds sanity gate: ({left_input_error:.3e}, {right_input_error:.3e})" ); + let left_mpo = fused_qtt_to_mpo(&input.left)?; + let right_mpo = fused_qtt_to_mpo(&input.right)?; + let patch_start = Instant::now(); + let prepared = PatchedMpoPair::new(&left_mpo, &right_mpo, INPUT_L2_RTOL, PATCH_CAP)?; + let patch_secs = patch_start.elapsed().as_secs_f64(); + let (left_patch_count, right_patch_count) = prepared.input_patch_counts(); + let (left_patch_chi, right_patch_chi) = prepared.input_patch_max_bonds(); + let (left_patch_params, right_patch_params) = prepared.input_patch_n_params(); anyhow::ensure!( - input_errors.0 <= input_sanity && input_errors.1 <= input_sanity, - "input sampled relative errors {input_errors:?} exceed {input_sanity:.3e}" - ); - let patched = PatchedMpoPair::from_tensortrains_with_input_rtol( - left_train, - right_train, - input_svd_l2_rtol, - rtol, - patch_cap, - )?; - let input_build_secs = build_started.elapsed().as_secs_f64(); - let input_patches = patched.input_patch_counts(); - let input_patch_bonds = patched.input_patch_max_bonds(); - let input_patch_params = patched.input_patch_n_params(); - eprintln!( - "prepared raw_chi={raw_input_chi} input_chi={input_chi} raw_params={raw_input_params:?} input_params={input_params:?} input_errors={input_errors:?} np_over_chi2=({:.3},{:.3}) patches={input_patches:?} patch_chi={input_patch_bonds:?} patch_params={input_patch_params:?} compress={input_compression_secs:.3}s build={input_build_secs:.3}s", - input_params.0 as f64 / (input_chi * input_chi) as f64, - input_params.1 as f64 / (input_chi * input_chi) as f64, + left_patch_chi.max(right_patch_chi) <= PATCH_CAP, + "input patch cap exceeded" ); - let input_record = serde_json::json!({ - "case": "mpo_mpo_aniso_input", - "n_gauss": n_gauss, - "r": r, - "box_l": box_l, - "sigma": sigma, - "rho_max": rho_max, - "spacing": spacing, - "box_padding": box_padding, - "r_extra": extra_bits, - "seed": seed, - "input_generator": input_generator, - "input_cache_key": cache_key, - "input_tci_rtol": input_tci_rtol, - "input_tci_cap": input_tci_cap, - "input_poly_degree": input_poly_degree, - "input_add_rtol": input_add_rtol, - "input_tci_local_abs_tol": input_tci_local_abs_tol, - "input_tci_initial_pivots": input_tci_initial_pivots, - "input_svd_l2_rtol": input_svd_l2_rtol, - "raw_input_chi": raw_input_chi, - "input_chi": input_chi, - "raw_input_params": raw_input_params, - "input_params": input_params, - "input_sampled_relative_errors": input_errors, - "input_sanity": input_sanity, - "input_error_samples": n_error_samples, - "max_input_chi": max_input_chi, - "np_over_chi_squared": [ - input_params.0 as f64 / (input_chi * input_chi) as f64, - input_params.1 as f64 / (input_chi * input_chi) as f64, - ], - "patch_cap": patch_cap, - "input_patch_counts": input_patches, - "input_patch_max_bonds": input_patch_bonds, - "input_patch_params": input_patch_params, - "input_cache_hit": cache_hit, - "input_cache_load_secs": input_cache_load_secs, - "input_compression_secs": input_compression_secs, - "input_build_secs": input_build_secs, - }); - fs::create_dir_all(&out_dir)?; - fs::write( - out_dir.join(format!( - "mpo_mpo_aniso_input-{input_generator}-n{n_gauss}-chi{input_chi}.json" - )), - serde_json::to_string_pretty(&input_record)?, - )?; - if input_only { - return Ok(()); - } + let input_chi = input.left.rank().max(input.right.rank()); + let input_params = simple_n_params(&input.left) + simple_n_params(&input.right); - let (global_train, global_timing) = time_median(warmups, runs, || { - patched - .contract_fit_global(rtol, input_chi) - .expect("global fit contraction failed") - }); - let (tree_partitioned, tree_timing) = time_median(warmups, runs, || { - patched - .contract_fit_treetn_partitioned(rtol, patch_cap) - .expect("PartitionedTreeTN fit contraction failed") + let (global_result, global_timing) = time_median(warmups, runs, || { + prepared.contract_fit_global(INPUT_L2_RTOL, GLOBAL_MAX_BOND) }); - let global_output = patched.finish_global_output(&global_train)?; - let tree_output = patched.finish_treetn_output(tree_partitioned)?; - - let error_seed = seed.wrapping_add(99); - let global_error = max_rel_error_vs_aniso_grid( - &global_output, - dy, - &f, - &g, - r, - box_l, - n_error_samples, - error_seed, + let global: TensorTrain = global_result?; + let global_params = tensortrain_n_params(&global); + let global_chi = global.max_bond_dim(); + let global_mpo = prepared.finish_global_output(&global)?; + let grid_step = 2.0 * input.box_l / (1usize << input.r) as f64; + let global_error = sampled_relative_l2_vs_aniso_grid( + &global_mpo, + grid_step, + &input.left_mixture, + &input.right_mixture, + input.r, + input.box_l, + ERROR_SAMPLES, + seed.wrapping_add(99), + )?; + anyhow::ensure!( + global_error <= ERROR_SANITY, + "global contraction error {global_error:.3e}" ); - let tree_error = max_rel_error_vs_aniso_grid( - &tree_output.mpo, - dy, - &f, - &g, - r, - box_l, - n_error_samples, - error_seed, + let common = common_params( + &input, + &config, + input_params, + left_patch_count, + right_patch_count, + left_patch_chi, + right_patch_chi, + left_patch_params, + right_patch_params, + patch_secs, + left_input_error, + right_input_error, ); - let common_params = serde_json::json!({ - "n_gauss": n_gauss, - "r": r, - "inner_l": inner_l, - "box_l": box_l, - "box_padding": box_padding, - "sigma": sigma, - "rho_max": rho_max, - "spacing": spacing, - "r_extra": extra_bits, - "input_tci_rtol": input_tci_rtol, - "input_tci_cap": input_tci_cap, - "input_svd_l2_rtol": input_svd_l2_rtol, - "raw_input_chi": raw_input_chi, - "raw_input_params": [raw_input_params.0, raw_input_params.1], - "input_params": [input_params.0, input_params.1], - "input_compression_secs": input_compression_secs, - "input_patch_cap": patch_cap, - "input_patch_counts": [input_patches.0, input_patches.1], - "input_patch_max_bonds": [input_patch_bonds.0, input_patch_bonds.1], - "input_patch_params": [input_patch_params.0, input_patch_params.1], - "global_contract_max_bond": input_chi, - "patched_contract_max_bond": patch_cap, - "fit_nfullsweeps": 1, - "contraction_svd_policy": "relative_squared_discarded_tail_sum", - "split_strategy": "sequential_y_first", - "runs": runs, - "warmups": warmups, - "n_error_samples": n_error_samples, - "error_seed": error_seed, - "input_cache_key": cache_key, - "input_cache_hit": cache_hit, - "input_cache_load_secs": input_cache_load_secs, - "error_metric": "max_rel_vs_quantics_grid_reference", - }); - let global_record = RunRecord { - schema_version: SCHEMA_VERSION, - case: "mpo_mpo_aniso_patched".into(), - algorithm: "global_fit_treetn".into(), - params: common_params.clone(), - seed, - tolerance: rtol, - wall_time_median_secs: global_timing.median_secs, - wall_times_secs: global_timing.runs_secs.clone(), - max_error: global_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: global_output.rank(), - output_bond_dims: global_output.link_dims(), - n_params: Some(mpo_n_params(&global_output)), - n_patches: None, - max_patch_bond: None, - rtol: Some(rtol), - input_build_secs: Some(input_build_secs), - }; write_record( - &out_dir, - &format!("mpo_mpo_aniso_patched-global_fit_treetn-n{n_gauss}-chi{input_chi}"), - &global_record, - )?; - write_arm( - &out_dir, - "patched_fit_treetn", - &tree_output, - &tree_timing, - tree_error, - input_chi, - input_build_secs, - seed, - rtol, - &common_params, + out_dir, + &format!("{CASE}-global_fit-chi{input_chi}"), + &RunRecord { + schema_version: SCHEMA_VERSION, + case: CASE.into(), + algorithm: "global_fit".into(), + params: common.clone(), + seed, + tolerance: INPUT_L2_RTOL, + wall_time_median_secs: global_timing.median_secs, + wall_times_secs: global_timing.runs_secs.clone(), + max_error: global_error, + input_max_bond_dim: input_chi, + output_max_bond_dim: global_chi, + output_bond_dims: global.bond_dims(), + n_params: Some(global_params), + n_patches: None, + max_patch_bond: None, + rtol: Some(INPUT_L2_RTOL), + input_build_secs: Some(input.build.as_secs_f64()), + }, )?; - eprintln!( - "global_fit_treetn: t={:.6}s error={global_error:.3e} output_chi={}", - global_timing.median_secs, - global_output.rank() - ); - eprintln!( - "patched_fit_treetn: t={:.6}s error={tree_error:.3e} output_patches={} output_chi={}", - tree_timing.median_secs, tree_output.n_patches, tree_output.max_patch_bond - ); + let (patched_result, patched_timing) = time_median(warmups, runs, || { + prepared.contract_fit_treetn_partitioned(INPUT_L2_RTOL, PATCH_CAP) + }); + let patched = patched_result?; + let patched_params = partitioned_treetn_n_params(&patched); + let patched_finished = prepared.finish_treetn_output(patched)?; anyhow::ensure!( - global_error <= sanity, - "global fit relative error {global_error:.3e} > {sanity:.3e}" + patched_finished.max_patch_bond <= PATCH_CAP, + "output patch cap exceeded" ); + let patched_error = sampled_relative_l2_vs_aniso_grid( + &patched_finished.mpo, + grid_step, + &input.left_mixture, + &input.right_mixture, + input.r, + input.box_l, + ERROR_SAMPLES, + seed.wrapping_add(99), + )?; anyhow::ensure!( - tree_error <= sanity, - "TreeTN relative error {tree_error:.3e} > {sanity:.3e}" + patched_error <= ERROR_SANITY, + "patched contraction error {patched_error:.3e}" ); - Ok(()) -} - -#[allow(clippy::too_many_arguments)] -fn write_arm( - out_dir: &std::path::Path, - algorithm: &str, - output: &PatchedMpoOutput, - timing: &t4a_bench::harness::Timing, - max_error: f64, - input_chi: usize, - input_build_secs: f64, - seed: u64, - rtol: f64, - params: &serde_json::Value, -) -> anyhow::Result<()> { - let record = RunRecord { - schema_version: SCHEMA_VERSION, - case: "mpo_mpo_aniso_patched".into(), - algorithm: algorithm.into(), - params: params.clone(), - seed, - tolerance: rtol, - wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs.clone(), - max_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: output.mpo.rank(), - output_bond_dims: output.mpo.link_dims(), - n_params: None, - n_patches: Some(output.n_patches), - max_patch_bond: Some(output.max_patch_bond), - rtol: Some(rtol), - input_build_secs: Some(input_build_secs), - }; + let mut patched_common = common; + patched_common["speedup_vs_global"] = + serde_json::json!(global_timing.median_secs / patched_timing.median_secs); write_record( out_dir, - &format!( - "mpo_mpo_aniso_patched-{algorithm}-n{}-chi{input_chi}", - params["n_gauss"] - ), - &record, - ) + &format!("{CASE}-patched_fit-chi{input_chi}"), + &RunRecord { + schema_version: SCHEMA_VERSION, + case: CASE.into(), + algorithm: "patched_fit".into(), + params: patched_common, + seed, + tolerance: INPUT_L2_RTOL, + wall_time_median_secs: patched_timing.median_secs, + wall_times_secs: patched_timing.runs_secs, + max_error: patched_error, + input_max_bond_dim: input_chi, + output_max_bond_dim: patched_finished.max_patch_bond, + output_bond_dims: vec![patched_finished.max_patch_bond], + n_params: Some(patched_params), + n_patches: Some(patched_finished.n_patches), + max_patch_bond: Some(patched_finished.max_patch_bond), + rtol: Some(INPUT_L2_RTOL), + input_build_secs: Some(input.build.as_secs_f64()), + }, + )?; + Ok(()) } -#[cfg(test)] -mod tests { - use super::*; - use std::time::{SystemTime, UNIX_EPOCH}; - use t4a_bench::gaussian::to_quantics_mpo_field; - - #[test] - fn l2_compression_reduces_or_preserves_input_size() { - let field = AnisoMixture2D::random(4, 1.0, 0.2, 3.0, 9); - let other = AnisoMixture2D::random(4, 1.0, 0.2, 3.0, 10); - let (left, _) = to_quantics_mpo_field(&field, 5, 1.0, 1.0e-8, 64).unwrap(); - let (right, _) = to_quantics_mpo_field(&other, 5, 1.0, 1.0e-8, 64).unwrap(); - let (mut left, mut right) = mpo_pair_to_tensortrains(&left, &right).unwrap(); - let before = (tensortrain_n_params(&left), tensortrain_n_params(&right)); - - truncate_tensortrain_l2(&mut left, 1.0e-6).unwrap(); - truncate_tensortrain_l2(&mut right, 1.0e-6).unwrap(); - - assert!(tensortrain_n_params(&left) <= before.0); - assert!(tensortrain_n_params(&right) <= before.1); - PatchedMpoPair::from_tensortrains_with_input_rtol(left, right, 1.0e-6, 1.0e-8, 16).unwrap(); - } - - #[test] - fn cached_inputs_round_trip_with_shared_index_identity() { - let field = AnisoMixture2D::random(2, 1.0, 0.2, 3.0, 7); - let other = AnisoMixture2D::random(2, 1.0, 0.2, 3.0, 8); - let (left, _) = to_quantics_mpo_field(&field, 4, 1.0, 1.0e-8, 32).unwrap(); - let (right, _) = to_quantics_mpo_field(&other, 4, 1.0, 1.0e-8, 32).unwrap(); - let original = PatchedMpoPair::new(&left, &right, 1.0e-8, 16).unwrap(); - let nonce = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_nanos(); - let path = - std::env::temp_dir().join(format!("t4a-mpo-cache-{}-{nonce}.h5", std::process::id())); - let path_str = path.to_string_lossy(); - let (left_train, right_train) = original.global_inputs(); - save_mps(&path_str, "left", left_train).unwrap(); - append_mps(&path_str, "right", right_train).unwrap(); - - let cached = PatchedMpoPair::from_tensortrains( - load_mps(&path_str, "left").unwrap(), - load_mps(&path_str, "right").unwrap(), - 1.0e-8, - 16, - ) - .unwrap(); - fs::remove_file(path).unwrap(); - - assert_eq!(cached.input_max_bond(), original.input_max_bond()); - assert_eq!(cached.input_patch_counts(), original.input_patch_counts()); - assert_eq!( - cached.input_patch_max_bonds(), - original.input_patch_max_bonds() - ); - } +#[allow(clippy::too_many_arguments)] +fn common_params( + input: &t4a_bench::gaussian_input::GaussianInputPair, + config: &GaussianInputConfig, + input_params: usize, + left_patch_count: usize, + right_patch_count: usize, + left_patch_chi: usize, + right_patch_chi: usize, + left_patch_params: usize, + right_patch_params: usize, + patch_secs: f64, + left_input_error: f64, + right_input_error: f64, +) -> serde_json::Value { + serde_json::json!({ + "n_gauss": config.n, "r": input.r, "box_l": input.box_l, + "sigma_minor": config.sigma_minor, "rho_max": config.rho_max, + "spacing": config.spacing, "polynomial_degree": config.polynomial_degree, + "interpolation_tolerance": config.interpolation_tolerance, + "addition_tolerance": config.addition_tolerance, + "input_l2_rtol": INPUT_L2_RTOL, "patch_cap": PATCH_CAP, + "raw_left_chi": input.raw_left_chi, "raw_right_chi": input.raw_right_chi, + "left_chi": input.left.rank(), "right_chi": input.right.rank(), + "raw_left_params": input.raw_left_params, "raw_right_params": input.raw_right_params, + "input_params": input_params, + "left_input_patch_count": left_patch_count, "right_input_patch_count": right_patch_count, + "left_input_max_patch_chi": left_patch_chi, "right_input_max_patch_chi": right_patch_chi, + "left_input_patch_params": left_patch_params, "right_input_patch_params": right_patch_params, + "cache_key": input.cache_key, "cache_hit": input.cache_hit, + "cache_load_secs": input.cache_load.as_secs_f64(), + "input_build_secs": input.build.as_secs_f64(), + "input_compression_secs": input.compression.as_secs_f64(), + "patch_build_secs": patch_secs, + "left_input_sampled_relative_l2": left_input_error, + "right_input_sampled_relative_l2": right_input_error, + "error_samples": ERROR_SAMPLES, + "internal_tolerance": INPUT_L2_RTOL, + "internal_tolerance_metric": "relative_l2_svd", + "external_error_metric": "sampled_relative_l2" + }) } diff --git a/src/bin/mpo_mpo_quantics.rs b/src/bin/mpo_mpo_quantics.rs deleted file mode 100644 index 890ac84..0000000 --- a/src/bin/mpo_mpo_quantics.rs +++ /dev/null @@ -1,247 +0,0 @@ -//! Case 2 runner: contraction of two quantics MPOs representing 2D Gaussian -//! mixtures, swept over the number of bits per variable for each algorithm. -//! -//! Default algorithms are `naive,zipup_simplett,zipup_treetn,fit_treetn`, -//! selectable with `BENCH_ALGOS`. Where both upstream engines implement an -//! algorithm, both are benchmarked as separate arms and the engine is recorded -//! as `engine` in every JSON record, so an engine difference shows up as its own -//! column instead of being folded into one. The only missing pair is simplett -//! fit, excluded for the upstream stub reason stated below. -//! -//! Fixed output budget, decided by the rank cap alone: the contraction is run -//! with the maximum bond dimension capped at the input rank (`chi_out <= -//! chi_in`, where `chi_in` is the larger of the two input MPO ranks), -//! identically for every algorithm, and the truncation tolerance handed to the -//! contraction is pinned inert. `BENCH_TOL` (default 1e-8) now scopes only the -//! input TCI construction in `to_quantics_mpo`, so it defines `chi_in` and thus -//! the instance. `BENCH_CONTRACT_TOL` (default 1e-15) is what every arm -//! receives as its truncation tolerance and is recorded as `contract_tol` in the -//! params of every record. At 1e-15 that tolerance never fires, so `chi_in` is -//! the only binding truncation control and the cases cannot be read ambiguously -//! as measuring whichever of the two constraints happened to bind first. All -//! arms therefore genuinely exhaust the same output budget unless their exact -//! rank is smaller, and the error column, the residual against the analytic -//! Gaussian integral recorded as `max_error` with -//! `error_metric = "max_rel_vs_analytic"`, is the discriminator between them. -//! Both engines truncate relative to the largest singular value, so at the same -//! nominal tolerance they discard the same singular values. -//! -//! What the fixed budget measures, as observed over the default sweep r = 6 to -//! 14 with the pinned rev: `naive` and `fit_treetn` land on the same error, -//! 5.7e-10 to 3.6e-9, which is below the reference floor the case was previously -//! credited with. The two zipup arms, `zipup_simplett` and `zipup_treetn`, agree -//! with each other to the last reported digit and sit four to five orders of -//! magnitude higher, 2.0e-5 to 1.1e-4. Every arm spends the whole budget, since -//! the tolerance no longer stops it early. So -//! the split is algorithmic rather than engine-driven: single-pass zip-up -//! truncation is what costs accuracy, and the two engines running it produce the -//! same answer. What zipup buys is speed: it is the fastest arm at every r and -//! stays between 0.015 s and 0.31 s across the sweep, while `naive` grows -//! steeply, from 0.02 s at r = 6 to 0.4 s at r = 8, 5.3 s at r = 10 and 16 to -//! 17 s at r = 12 and 14, because it forms the full -//! contracted bond before truncating. `fit_treetn` reaches naive accuracy at a -//! fraction of the naive cost, under 0.75 s at every r. -//! -//! The `zipup_treetn` and `fit_treetn` columns run on the treetn engine, -//! reached through `tensor4all_itensorlike::TensorTrain::contract` with -//! `ContractOptions::zipup()` and `ContractOptions::fit()` respectively (see -//! `mpo_contract`). They share the same bridge, max rank and SVD policy, so the -//! only difference between them is the contraction method. That is the same -//! engine case 1 uses for its elementwise fit. -//! `tensor4all_simplett::mpo::contract_fit` is deliberately NOT benchmarked: at -//! the pinned upstream rev (tensor4all-rs c9ecb7f) its local update -//! `update_two_site_core` is still a placeholder that leaves the core -//! untouched, so that path degenerates to naive plus dead sweeps -//! (tensor4all-rs#571). -//! -//! The pinned rev includes tensor4all-rs#574, which changed simplett in three -//! ways that this case sees directly: MPO factorize truncation became relative -//! to the largest singular value instead of absolute, `contract_zipup`'s scalar -//! loop became an einsum (about 800x faster), and `contract_naive`'s -//! compression sweep now establishes a right-to-left QR gauge before -//! truncating, which dropped its error by about three orders of magnitude onto -//! the variational fit result. -//! -//! `fit_treetn` is run at a fixed sweep count (`mpo_contract::FIT_NSWEEPS`), -//! which is part of the benchmark definition: its cost is linear in the sweep -//! count, so the timing column is only comparable against the naive and zipup -//! arms at a stated number of sweeps. -//! -//! Default sweep size: the quantics rank of the default mixture saturates -//! around chi = 70 to 80. `naive` is the only expensive arm, since it forms the -//! full contracted bond of size chi^2 before truncating; every other arm stays -//! around a second or less across the default range. The defaults (r = 6, 8, -//! 10, 12, 14 with 3 timed runs, no warmup) size the whole case at roughly two -//! minutes on the maintainer's Mac, nearly all of it naive at r = 10 to 14, -//! which costs 5 to 17 s per run there. That arm is memory bound on a machine -//! with less headroom, where the same points cost 16 to 48 s per run, so the -//! wall time of the whole case is a property of the machine as much as of the -//! sweep (README known issue 10). Extend with for example -//! `BENCH_RS=6,8,10,12,14,16 BENCH_RUNS=5` for the heavy tail, and restrict -//! `BENCH_ALGOS` to drop naive if only the cheap arms are wanted. - -use std::path::PathBuf; -use t4a_bench::gaussian::{to_quantics_mpo, GaussianMixture2D}; -use t4a_bench::harness::time_median; -use t4a_bench::mpo_contract::{ - max_rel_error_vs_analytic, mpo_contract, mpo_n_params, MpoAlgo, FIT_NSWEEPS, -}; -use t4a_bench::record::{write_record, RunRecord, SCHEMA_VERSION}; - -fn env_or(key: &str, default: T) -> T { - std::env::var(key) - .ok() - .and_then(|v| v.parse().ok()) - .unwrap_or(default) -} - -fn parse_algo(s: &str) -> MpoAlgo { - match s { - "naive" => MpoAlgo::Naive, - "zipup_simplett" => MpoAlgo::ZipupSimplett, - "zipup_treetn" => MpoAlgo::ZipupTreetn, - "fit_treetn" => MpoAlgo::FitTreetn, - other => panic!("unknown algorithm {other}"), - } -} - -fn main() -> anyhow::Result<()> { - let rs: Vec = std::env::var("BENCH_RS") - .unwrap_or_else(|_| "6,8,10,12,14".into()) - .split(',') - .map(|s| s.trim().parse().unwrap()) - .collect(); - let ngauss: usize = env_or("BENCH_NGAUSS", 8); - let box_l: f64 = env_or("BENCH_BOX_L", 6.0); - let alpha_lo: f64 = env_or("BENCH_ALPHA_LO", 0.5); - let alpha_hi: f64 = env_or("BENCH_ALPHA_HI", 8.0); - // Instance tolerance: this defines chi_in through the input TCI, and nothing - // else. It is what `RunRecord::tolerance` and the Julia-check metadata - // report, since both describe the inputs rather than the contraction. - let tol: f64 = env_or("BENCH_TOL", 1e-8); - // Contraction tolerance, pinned inert so the rank cap chi_in is the only - // binding truncation control for every arm. - let contract_tol: f64 = env_or("BENCH_CONTRACT_TOL", 1e-15); - let max_bond: usize = env_or("BENCH_MAX_BOND", 512); - // Since tensor4all-rs#574 the whole default sweep costs seconds, so three - // timed runs are affordable and the reported median is more stable than a - // single sample. Raise `BENCH_RUNS` further for the heavy tail. - let runs: usize = env_or("BENCH_RUNS", 3); - let warmups: usize = env_or("BENCH_WARMUPS", 0); - let seed: u64 = env_or("BENCH_SEED", 0); - // With the output budget fixed at chi_in, truncation error is the quantity - // being measured, not a defect, so the gate only screens order-unity - // wrongness rather than certifying precision. - let sanity: f64 = env_or("BENCH_SANITY", 1e-2); - let algos: Vec = std::env::var("BENCH_ALGOS") - .unwrap_or_else(|_| "naive,zipup_simplett,zipup_treetn,fit_treetn".into()) - .split(',') - .map(|s| s.trim().to_string()) - .collect(); - let out_dir = - PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| "result/dev/raw".into())); - - // Accuracy check sampling, recorded in every record's params. - let n_error_samples: usize = 128; - let error_seed: u64 = seed.wrapping_add(99); - - let f = GaussianMixture2D::random(ngauss, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(1)); - let g = GaussianMixture2D::random(ngauss, box_l, (alpha_lo, alpha_hi), seed.wrapping_add(2)); - - let mut failures = Vec::new(); - for &r in &rs { - let (fa, dy) = to_quantics_mpo(&f, r, box_l, tol, max_bond)?; - let (gb, _) = to_quantics_mpo(&g, r, box_l, tol, max_bond)?; - let input_chi = fa.rank().max(gb.rank()); - eprintln!("r={r} input_chi={input_chi}"); - - // An empty EXPORT_HDF5 counts as unset, so `EXPORT_HDF5=` disables export. - if let Some(dir) = std::env::var("EXPORT_HDF5").ok().filter(|d| !d.is_empty()) { - std::fs::create_dir_all(&dir)?; - let h5 = format!("{dir}/instance-r{r}.h5"); - // Export the FUSED site-dim-4 TTs (before the Tensor4 conversion), - // so `save_mps` applies directly and ITensorMPS.jl sees one site - // index of dimension 4 per site. - let (ftt, _) = t4a_bench::gaussian::to_quantics_fused_tt(&f, r, box_l, tol, max_bond)?; - let (gtt, _) = t4a_bench::gaussian::to_quantics_fused_tt(&g, r, box_l, tol, max_bond)?; - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "f", &ftt, false)?; - t4a_bench::hdf5_export::save_tt_as_mps(&h5, "g", >t, true)?; - let meta = serde_json::json!({ - "schema_version": 1, - "case": "mpo_mpo_quantics", - "r": r, - "box_l": box_l, - "tolerance": tol, - "f": {"weights": f.weights, "alphas": f.alphas, "centers": f.centers}, - "g": {"weights": g.weights, "alphas": g.alphas, "centers": g.centers}, - }); - std::fs::write( - format!("{dir}/instance-r{r}.json"), - serde_json::to_string_pretty(&meta)?, - )?; - } - - for algo_name in &algos { - let algo = parse_algo(algo_name); - let (h, timing) = time_median(warmups, runs, || { - mpo_contract(algo, &fa, &gb, contract_tol, input_chi).expect("contraction failed") - }); - let max_error = - max_rel_error_vs_analytic(&h, dy, &f, &g, r, box_l, n_error_samples, error_seed); - let rec = RunRecord { - schema_version: SCHEMA_VERSION, - case: "mpo_mpo_quantics".into(), - algorithm: algo_name.clone(), - params: serde_json::json!({ - "r": r, "n_gauss": ngauss, "box_l": box_l, - "alpha_range": [alpha_lo, alpha_hi], "max_bond": max_bond, - // Output budget shared by every algorithm: the input rank. - "contract_max_bond": input_chi, - // Truncation tolerance the arms actually ran with, pinned - // inert so the cap above is what decides. The top-level - // `tolerance` field is the instance tolerance instead. - "contract_tol": contract_tol, - "runs": runs, "warmups": warmups, - "n_error_samples": n_error_samples, "error_seed": error_seed, - "error_metric": "max_rel_vs_analytic", - // Upstream engine that actually ran this arm. - "engine": algo.engine(), - // Part of the benchmark definition for the fit arm. - "fit_nsweeps": FIT_NSWEEPS, - }), - seed, - tolerance: tol, - wall_time_median_secs: timing.median_secs, - wall_times_secs: timing.runs_secs, - max_error, - input_max_bond_dim: input_chi, - output_max_bond_dim: h.rank(), - output_bond_dims: h.link_dims(), - n_params: Some(mpo_n_params(&h)), - n_patches: None, - max_patch_bond: None, - rtol: None, - input_build_secs: None, - }; - write_record( - &out_dir, - &format!("mpo_mpo_quantics-{algo_name}-r{r}"), - &rec, - )?; - eprintln!( - " {algo_name}: t={:.4}s rel_err={max_error:.2e} chi_out={}", - timing.median_secs, - h.rank() - ); - if max_error > sanity { - failures.push(format!( - "{algo_name} r={r}: rel err {max_error:.2e} > {sanity:.2e}" - )); - } - } - } - if !failures.is_empty() { - anyhow::bail!("sanity failures:\n{}", failures.join("\n")); - } - Ok(()) -} diff --git a/src/elementwise.rs b/src/elementwise.rs index 4c866c7..06acee3 100644 --- a/src/elementwise.rs +++ b/src/elementwise.rs @@ -3,16 +3,15 @@ //! two cases that use them. //! //! The product itself is generic over [`BenchScalar`], because case 1 works on -//! a complex Fourier series and case 3 on a real 2D Gaussian mixture, and both -//! run the same four arms. The error metrics are not generic: each one compares -//! against the analytic reference of its own case, which fixes the scalar type -//! (`Complex64` for case 1, `f64` for case 3). +//! a complex Fourier series and case 2 on a real 2D Gaussian mixture. The error +//! metrics compare against the analytic reference of their own case, fixing the +//! scalar type to `Complex64` for case 1 and `f64` for case 2. use num_complex::Complex64; use tensor4all_simplett::{tensor3_from_data, AbstractTensorTrain, SimpleTensorTrain, Tensor3Ops}; use crate::fourier::{compress_svd, FourierSeries}; -use crate::gaussian::{grid_coord, Field2D, GaussianMixture2D}; +use crate::gaussian::{grid_coord, Field2D}; use crate::harness::{index_to_bits, sample_grid_indices}; use crate::scalar::BenchScalar; @@ -38,15 +37,9 @@ pub enum ElementwiseAlgo { /// absolute or scaled by the sampled output magnitude of the bond is a separate /// upstream switch, `AciOptions::scale_tolerance`, whose upstream default is /// scale-relative since tensor4all-rs#619. This enum makes the choice explicit -/// at every call site rather than inheriting that default, because the two -/// families of cases want opposite things. The fixed-budget cases (2, 3 and 4) -/// want the same "tolerance is unreachable, the cap decides" regime for ACI as -/// for the SVD arms, so they ask for [`AciTolerance::ScaleRelative`]. Cases 1 -/// and 5 are tolerance-driven and judged by one error that is normalized -/// globally, so they ask for [`AciTolerance::Absolute`]: a per-bond -/// normalization would hold each region to its own scale, which is not the -/// quantity either case reports (see the case-5 tolerance discussion in the -/// README). +/// at every call site rather than inheriting that default. Case 1 and the +/// patched arm of case 2 use an absolute residual. The global ACI arm of case 2 +/// uses a scale-relative residual. Records name the selected metric explicitly. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum AciTolerance { /// Absolute pivot error threshold. @@ -57,7 +50,7 @@ pub enum AciTolerance { } impl ElementwiseAlgo { - /// Which engine actually runs this arm, recorded in every case-3 record. + /// Which engine actually runs this arm. /// /// `Naive` is the local bond-Kronecker product plus an SVD sweep written in /// this crate on top of `simplett` primitives, so it is labelled `local` @@ -203,29 +196,27 @@ pub fn max_error_vs_series( .fold(0.0, f64::max) } -/// Case 3: relative max error of the fused 2D product train against the exact -/// pointwise product of the two Gaussian mixtures. -/// -/// `h` is a fused quantics train on `[-L, L)^2` with `r` sites of dimension 4, -/// local index `x_bit + 2 * y_bit` and the most significant bit first, which is -/// the layout `gaussian::to_quantics_fused_tt` produces. The normalization -/// matches case 2: the largest sampled `|reference|`, so the two cases report -/// the same kind of number under `error_metric = "max_rel_vs_analytic"`. -pub fn max_rel_error_vs_mixture_product( - h: &SimpleTensorTrain, - f: &GaussianMixture2D, - g: &GaussianMixture2D, +/// Deterministic sampled relative-L2 error against an exact Fourier series. +pub fn sampled_relative_l2_vs_series( + output: &SimpleTensorTrain, + exact: &FourierSeries, r: usize, - box_l: f64, - n_samples: usize, + samples: usize, seed: u64, ) -> f64 { - max_rel_error_vs_product(h, f, g, r, box_l, n_samples, seed) + let (error, reference) = sample_grid_indices(r, samples, seed).into_iter().fold( + (0.0, 0.0), + |(error, reference), index| { + let x = index as f64 / (1u64 << r) as f64; + let expected = exact.eval(x); + let delta = output.evaluate(&index_to_bits(index, r)).unwrap() - expected; + (error + delta.norm_sqr(), reference + expected.norm_sqr()) + }, + ); + (error / reference.max(f64::MIN_POSITIVE)).sqrt() } -/// [`max_rel_error_vs_mixture_product`] for any pair of [`Field2D`] instances, so -/// that the two case-5 families share one error metric. Same sampling, same -/// normalization, same reported `error_metric`. +/// Sampled relative maximum error against the exact pointwise product. pub fn max_rel_error_vs_product( h: &SimpleTensorTrain, f: &A, @@ -235,142 +226,62 @@ pub fn max_rel_error_vs_product( n_samples: usize, seed: u64, ) -> f64 { - let xs = sample_grid_indices(r, n_samples, seed); - let ys = sample_grid_indices(r, n_samples, seed.wrapping_add(1)); - let mut max_abs = 0.0f64; - let mut max_ref = 0.0f64; - for (&ix, &iy) in xs.iter().zip(&ys) { - let x = grid_coord(ix, r, box_l); - let y = grid_coord(iy, r, box_l); - let xb = index_to_bits(ix, r); - let yb = index_to_bits(iy, r); - let fused: Vec = (0..r).map(|n| xb[n] + 2 * yb[n]).collect(); - let got = h.evaluate(&fused).unwrap(); - let want = f.eval(x, y) * g.eval(x, y); - max_abs = max_abs.max((got - want).abs()); - max_ref = max_ref.max(want.abs()); - } - max_abs / max_ref.max(f64::MIN_POSITIVE) -} - -/// Ratio at which the sampled elementwise product counts as numerically zero. -/// -/// The relative error of cases 3 and 4 is normalized by the largest sampled -/// `|f * g|`. If the two mixtures barely overlap, that number collapses -/// exponentially while `max |f|` and `max |g|` stay of order one, and the -/// reported relative error stops measuring anything. A product scale below -/// `DEGENERACY_THRESHOLD` times the product of the two input scales means the -/// sampled reference has lost at least six orders of magnitude to the lack of -/// overlap, which is far outside anything a healthy instance produces: the -/// default case-3 and case-4 instances sit at a ratio near 0.5, five to six -/// orders of magnitude above the threshold. -pub const DEGENERACY_THRESHOLD: f64 = 1e-6; - -/// Scales of the case-3 and case-4 reference, all measured over one and the -/// same set of sampled grid points. -#[derive(Clone, Copy, Debug)] -pub struct MixtureProductScales { - /// `max |f(x, y) * g(x, y)|`, the normalization of the relative error. - pub ref_scale: f64, - /// `max |f(x, y)|`. - pub input_scale_f: f64, - /// `max |g(x, y)|`. - pub input_scale_g: f64, -} - -impl MixtureProductScales { - /// True when the sampled product has collapsed relative to the inputs, so - /// the relative error metric of the case is meaningless. - pub fn is_degenerate(&self) -> bool { - self.ref_scale < DEGENERACY_THRESHOLD * self.input_scale_f * self.input_scale_g - } -} - -/// Reference and input scales at the same sampled grid points that -/// [`max_rel_error_vs_mixture_product`] uses, given the same `r`, `box_l`, -/// `n_samples` and `seed`. -pub fn mixture_product_scales( - f: &GaussianMixture2D, - g: &GaussianMixture2D, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> MixtureProductScales { - product_scales(f, g, r, box_l, n_samples, seed) -} - -/// [`mixture_product_scales`] for any pair of [`Field2D`] instances. -pub fn product_scales( - f: &A, - g: &B, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> MixtureProductScales { - let xs = sample_grid_indices(r, n_samples, seed); - let ys = sample_grid_indices(r, n_samples, seed.wrapping_add(1)); - let mut s = MixtureProductScales { - ref_scale: 0.0, - input_scale_f: 0.0, - input_scale_g: 0.0, - }; - for (&ix, &iy) in xs.iter().zip(&ys) { - let x = grid_coord(ix, r, box_l); - let y = grid_coord(iy, r, box_l); - let (fv, gv) = (f.eval(x, y), g.eval(x, y)); - s.ref_scale = s.ref_scale.max((fv * gv).abs()); - s.input_scale_f = s.input_scale_f.max(fv.abs()); - s.input_scale_g = s.input_scale_g.max(gv.abs()); - } - s + let (error, scale) = sampled_product_values(h, f, g, r, box_l, n_samples, seed) + .into_iter() + .fold((0.0_f64, 0.0_f64), |(error, scale), (got, expected)| { + (error.max((got - expected).abs()), scale.max(expected.abs())) + }); + error / scale.max(f64::MIN_POSITIVE) } -/// Fail-fast guard for cases 3 and 4: refuse to benchmark an instance whose -/// elementwise product is numerically zero at the sampled points. -/// -/// Returns the scales on success so the caller can record them. -pub fn check_mixture_product_not_degenerate( - f: &GaussianMixture2D, - g: &GaussianMixture2D, +/// Deterministic sampled relative-L2 error against the exact pointwise product. +pub fn sampled_relative_l2_vs_product( + output: &SimpleTensorTrain, + left: &A, + right: &B, r: usize, box_l: f64, - n_samples: usize, + samples: usize, seed: u64, -) -> anyhow::Result { - check_product_not_degenerate(f, g, r, box_l, n_samples, seed) +) -> f64 { + let (error, reference) = sampled_product_values(output, left, right, r, box_l, samples, seed) + .into_iter() + .fold((0.0, 0.0), |(error, reference), (got, expected)| { + ( + error + (got - expected).powi(2), + reference + expected.powi(2), + ) + }); + (error / reference.max(f64::MIN_POSITIVE)).sqrt() } -/// [`check_mixture_product_not_degenerate`] for any pair of [`Field2D`] -/// instances, at the same threshold. The anisotropic spike family of case 5 holds -/// its spacing-to-width ratio fixed as `N` grows, which is exactly what keeps this -/// guard passing there: the sampled product stays at about half of -/// `max|f| max|g|` at every `N`. -pub fn check_product_not_degenerate( - f: &A, - g: &B, +fn sampled_product_values( + output: &SimpleTensorTrain, + left: &A, + right: &B, r: usize, box_l: f64, - n_samples: usize, + samples: usize, seed: u64, -) -> anyhow::Result { - let s = product_scales(f, g, r, box_l, n_samples, seed); - anyhow::ensure!( - !s.is_degenerate(), - "degenerate instance at r={r}, box_l={box_l}: the two mixtures barely overlap, so the \ - elementwise product is numerically zero at the sampled points (ref_scale {:.3e} against \ - input_scale_f {:.3e} and input_scale_g {:.3e}, ratio {:.3e} below the threshold {:.0e}) \ - and the relative error metric, which divides by ref_scale, is meaningless. Lower \ - BENCH_ALPHA_HI so the Gaussians are wider, or raise the density (more Gaussians, or a \ - smaller box).", - s.ref_scale, - s.input_scale_f, - s.input_scale_g, - s.ref_scale / (s.input_scale_f * s.input_scale_g).max(f64::MIN_POSITIVE), - DEGENERACY_THRESHOLD - ); - Ok(s) +) -> Vec<(f64, f64)> { + let xs = sample_grid_indices(r, samples, seed); + let ys = sample_grid_indices(r, samples, seed.wrapping_add(1)); + xs.iter() + .zip(&ys) + .map(|(&ix, &iy)| { + let x = grid_coord(ix, r, box_l); + let y = grid_coord(iy, r, box_l); + let fused: Vec<_> = index_to_bits(ix, r) + .into_iter() + .zip(index_to_bits(iy, r)) + .map(|(x, y)| x + 2 * y) + .collect(); + ( + output.evaluate(&fused).unwrap(), + left.eval(x, y) * right.eval(x, y), + ) + }) + .collect() } #[cfg(test)] @@ -413,116 +324,6 @@ mod tests { } } - /// Case 3 at its own fixed output budget: every arm capped at `chi_in`, the - /// larger input rank, and judged only on the error it returns for it. - /// - /// The budget is the cap alone: the tolerance handed to the arms is the - /// runner's inert 1e-15 and the aci arm runs scale-relative, so every arm is - /// expected to spend the whole budget rather than stop at a tolerance. - /// - /// The bounds are per arm because the arms are not comparable here. Measured - /// at the pinned revision on this instance (r = 8, 3 Gaussians, chi_in 62): - /// naive, fit and aci all land on 1.4e-8 at the full chi_out of 62, and zipup - /// returns 8.3e-1 for the same budget. Every bound carries about an order of - /// magnitude of margin, since the quantics TCI construction is not - /// bit-reproducible and chi_in moves by one between runs. The zipup bound is - /// loose on purpose: at this budget a single-pass truncation of an - /// elementwise product has no accuracy left to defend (the runner's default - /// instance reaches 9.2e-1 at r = 10), so what the bound guards is that the - /// arm still returns a finite result of roughly the right scale. This test - /// also covers the real-scalar (`f64`) path through all four arms, which case - /// 1 does not exercise. - #[test] - fn gauss2d_arms_meet_their_error_bounds_at_fixed_budget() { - use crate::gaussian::{to_quantics_fused_tt, GaussianMixture2D}; - - let (r, l) = (8, 6.0); - let f = GaussianMixture2D::random(3, l, (0.5, 8.0), 1); - let g = GaussianMixture2D::random(3, l, (0.5, 8.0), 2); - let (fa, _) = to_quantics_fused_tt(&f, r, l, 1e-8, 512).unwrap(); - let (gb, _) = to_quantics_fused_tt(&g, r, l, 1e-8, 512).unwrap(); - let chi_in = fa.rank().max(gb.rank()); - - // The third element says whether the arm is expected to spend the whole - // budget. The three SVD-based arms keep everything the cap allows, since - // the tolerance can no longer stop them; aci is interpolation-based and - // may settle below the cap if its pivot search saturates first, so it is - // only held to the cap as an upper bound. - for (algo, bound, exhausts_budget) in [ - (ElementwiseAlgo::Naive, 1e-6, true), - (ElementwiseAlgo::Zipup, 2.0, true), - (ElementwiseAlgo::Fit, 1e-6, true), - (ElementwiseAlgo::Aci, 1e-6, false), - ] { - // The budget is the cap, so the tolerance is pinned inert, exactly as - // the runner does it. - let out = - elementwise_product(algo, &fa, &gb, 1e-15, chi_in, AciTolerance::ScaleRelative) - .unwrap(); - assert!( - out.rank() <= chi_in, - "{algo:?}: chi_out {} exceeds the budget {chi_in}", - out.rank() - ); - if exhausts_budget { - assert_eq!( - out.rank(), - chi_in, - "{algo:?}: chi_out {} fell short of the budget {chi_in}, so something \ - other than the cap truncated it", - out.rank() - ); - } - let err = max_rel_error_vs_mixture_product(&out, &f, &g, r, l, 128, 99); - println!( - "{algo:?}: rel err {err:.3e} (bound {bound:.0e}), chi_out {} of {chi_in}", - out.rank() - ); - assert!( - err.is_finite() && err < bound, - "{algo:?}: rel err {err} exceeds {bound}" - ); - } - } - - /// Two mixtures whose supports sit in opposite corners of the box: each one - /// is of order one where it lives, but the product is zero to machine - /// precision everywhere, so the guard must refuse the instance. - #[test] - fn degeneracy_guard_fires_on_non_overlapping_mixtures() { - use crate::gaussian::GaussianMixture2D; - - let (r, l) = (6, 4.0); - let far = |sign: f64| GaussianMixture2D { - weights: vec![1.0], - alphas: vec![50.0], - centers: vec![(sign * l / 2.0, sign * l / 2.0)], - }; - let (f, g) = (far(-1.0), far(1.0)); - - let s = mixture_product_scales(&f, &g, r, l, 128, 7); - println!( - "ref_scale {:.3e}, input scales {:.3e} and {:.3e}", - s.ref_scale, s.input_scale_f, s.input_scale_g - ); - assert!(s.input_scale_f > 1e-3 && s.input_scale_g > 1e-3); - assert!(s.is_degenerate(), "guard predicate missed a zero product"); - - let err = check_mixture_product_not_degenerate(&f, &g, r, l, 128, 7) - .expect_err("the guard must reject this instance"); - let msg = err.to_string(); - assert!(msg.contains("barely overlap"), "unexpected message: {msg}"); - assert!(msg.contains("BENCH_ALPHA_HI"), "unexpected message: {msg}"); - - // A healthy instance of the same shape must pass, so the guard is not - // simply always firing. - let f2 = GaussianMixture2D::random(8, 6.0, (0.5, 8.0), 1); - let g2 = GaussianMixture2D::random(8, 6.0, (0.5, 8.0), 2); - let s2 = check_mixture_product_not_degenerate(&f2, &g2, 8, 6.0, 128, 99).unwrap(); - println!("default-like instance: ref_scale {:.3e}", s2.ref_scale); - assert!(!s2.is_degenerate()); - } - /// Guards against a dispatch swap between the arms of `elementwise_product`. /// With a forced truncation (`max_bond = 4` on a k=6 instance) the four /// algorithms are no longer interchangeable: they land on genuinely different diff --git a/src/gaussian.rs b/src/gaussian.rs index 1b8a3f3..89135fc 100644 --- a/src/gaussian.rs +++ b/src/gaussian.rs @@ -1,111 +1,185 @@ -//! 2D Gaussian mixtures: analytic y-integral and quantics MPO construction. +//! Randomly rotated anisotropic Gaussian mixtures and their quantics representation. -use std::collections::HashMap; - -use rand::Rng; -use rand::SeedableRng; +use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; -use tensor4all_interpolativeqtt::{ - direct_product_core_tensors, interpolate_multi_scale, interpolate_multi_scale_nd, - InterpolativeQttOptions, -}; -use tensor4all_quanticstci::{ - quanticscrossinterpolate, DiscretizedGrid, QtciOptions, UnfoldingScheme, -}; +use tensor4all_interpolativeqtt::{interpolate_multi_scale_nd, InterpolativeQttOptions}; use tensor4all_simplett::mpo::{tensor4_from_data, MPO}; use tensor4all_simplett::{ AbstractTensorTrain, CompressionMethod, CompressionOptions, SimpleTensorTrain, Tensor3Ops, }; -/// A scalar function of two variables that a benchmark case can compress. -/// -/// The two instance families of case 5 differ only in what they evaluate, so -/// every piece of machinery that samples a function (the quantics construction, -/// the degeneracy guard, the error metric, the patched input construction) is -/// written against this trait rather than against one concrete mixture. `Clone` -/// and `'static` are required because the quantics construction moves an owned -/// copy of the function into the closure it hands to the cross interpolation. -pub trait Field2D: Clone + 'static { +/// A scalar function of two variables. +pub trait Field2D { /// Value at `(x, y)`. fn eval(&self, x: f64, y: f64) -> f64; } -/// Construct one axis-aligned Gaussian as a quantics MPO. +/// A sum of independently rotated anisotropic 2D Gaussians. /// -/// Each one-variable factor is built by multiscale interpolative QTT with its -/// center marked as the interval that must remain refined. The factors are then -/// combined core-wise, without another interpolation or approximation. -/// -/// This construction assumes `r` is large enough to resolve both Gaussian -/// widths on `[-box_l, box_l)`. It does not attempt to detect an under-resolved -/// grid. -pub fn axis_aligned_gaussian_mpo( - r: usize, - box_l: f64, - center: (f64, f64), - alpha: (f64, f64), - weight: f64, - polynomial_degree: usize, - tolerance: f64, -) -> anyhow::Result> { - anyhow::ensure!(r >= 2, "an interpolative QTT needs at least two bits"); - anyhow::ensure!(box_l.is_finite() && box_l > 0.0, "invalid box size"); - anyhow::ensure!( - center.0.abs() < box_l && center.1.abs() < box_l, - "Gaussian center is outside the box" - ); - anyhow::ensure!( - alpha.0.is_finite() && alpha.0 > 0.0 && alpha.1.is_finite() && alpha.1 > 0.0, - "invalid Gaussian width" - ); - anyhow::ensure!(weight.is_finite(), "invalid Gaussian weight"); - anyhow::ensure!( - tolerance.is_finite() && tolerance >= 0.0, - "invalid interpolation tolerance" - ); +/// Term `i` is `w_i exp(-(a_i dx^2 + 2 b_i dx dy + c_i dy^2))`. +#[derive(Clone, Debug)] +pub struct AnisoMixture2D { + /// Positive prefactors `w_i`. + pub weights: Vec, + /// Positive-definite quadratic forms `(a_i, b_i, c_i)`. + pub quad: Vec<(f64, f64, f64)>, + /// Centers `(cx_i, cy_i)`. + pub centers: Vec<(f64, f64)>, +} - let options = InterpolativeQttOptions::default().with_tolerance(tolerance); - let x = interpolate_multi_scale( - |value| weight * (-alpha.0 * (value - center.0).powi(2)).exp(), - -box_l, - box_l, - r, - polynomial_degree, - &[center.0], - &options, - )?; - let y = interpolate_multi_scale( - |value| (-alpha.1 * (value - center.1).powi(2)).exp(), - -box_l, - box_l, - r, - polynomial_degree, - &[center.1], - &options, - )?; +impl AnisoMixture2D { + /// Draw the benchmark family on `[-box_l, box_l)^2`. + /// + /// Weights are uniform in `[0.5, 1.5)`, aspect ratios are log-uniform in + /// `[1, rho_max]`, orientations are uniform in `[0, pi)`, and centers are + /// uniform in the inner 90 percent of the box. Draw order is part of the + /// deterministic instance definition. + pub fn random(n: usize, box_l: f64, sigma_minor: f64, rho_max: f64, seed: u64) -> Self { + assert!(n > 0); + assert!(box_l.is_finite() && box_l > 0.0); + assert!(sigma_minor.is_finite() && sigma_minor > 0.0); + assert!(rho_max.is_finite() && rho_max > 1.0); + let mut rng = ChaCha8Rng::seed_from_u64(seed); + let half = 0.9 * box_l; + let a_minor = 1.0 / (2.0 * sigma_minor * sigma_minor); + let mut weights = Vec::with_capacity(n); + let mut quad = Vec::with_capacity(n); + let mut centers = Vec::with_capacity(n); + for _ in 0..n { + weights.push(rng.random_range(0.5..1.5)); + let rho = rho_max.powf(rng.random_range(0.0..1.0)); + let theta = rng.random_range(0.0..std::f64::consts::PI); + let a_major = a_minor / (rho * rho); + let (sin, cos) = theta.sin_cos(); + quad.push(( + a_major * cos * cos + a_minor * sin * sin, + (a_major - a_minor) * sin * cos, + a_major * sin * sin + a_minor * cos * cos, + )); + centers.push((rng.random_range(-half..half), rng.random_range(-half..half))); + } + Self { + weights, + quad, + centers, + } + } - let tensors = x - .site_tensors() - .iter() - .zip(y.site_tensors()) - .map(|(x_core, y_core)| { - let fused = direct_product_core_tensors(&[x_core.clone(), y_core.clone()])?; - let mut data = - Vec::with_capacity(fused.left_dim() * fused.site_dim() * fused.right_dim()); - for right in 0..fused.right_dim() { - for y_bit in 0..2 { - for x_bit in 0..2 { - for left in 0..fused.left_dim() { - data.push(*fused.get3(left, x_bit + 2 * y_bit, right)); - } - } + /// Evaluate the exact mixture. + pub fn eval(&self, x: f64, y: f64) -> f64 { + self.weights + .iter() + .zip(&self.quad) + .zip(&self.centers) + .map(|((&weight, &(a, b, c)), &(cx, cy))| { + let (dx, dy) = (x - cx, y - cy); + weight * (-(a * dx * dx + 2.0 * b * dx * dy + c * dy * dy)).exp() + }) + .sum() + } + + /// First derivatives with respect to the first and second coordinates. + pub fn gradient(&self, x: f64, y: f64) -> (f64, f64) { + self.weights.iter().zip(&self.quad).zip(&self.centers).fold( + (0.0, 0.0), + |(gx, gy), ((&weight, &(a, b, c)), &(cx, cy))| { + let (dx, dy) = (x - cx, y - cy); + let value = weight * (-(a * dx * dx + 2.0 * b * dx * dy + c * dy * dy)).exp(); + ( + gx - 2.0 * (a * dx + b * dy) * value, + gy - 2.0 * (b * dx + c * dy) * value, + ) + }, + ) + } + + /// Interpolate each Gaussian independently and add the QTTs by balanced reduction. + /// + /// Every pair is compressed immediately, so reduction depth is logarithmic and + /// no exact sum with bond dimension proportional to the term count is formed. + /// `r` must be large enough to resolve the minor Gaussian width. + pub fn to_interpolative_qtt( + &self, + r: usize, + box_l: f64, + polynomial_degree: usize, + interpolation_tolerance: f64, + addition_tolerance: f64, + ) -> anyhow::Result> { + anyhow::ensure!( + self.weights.len() == self.quad.len() && self.weights.len() == self.centers.len(), + "anisotropic mixture arrays have different lengths" + ); + anyhow::ensure!(!self.weights.is_empty(), "anisotropic mixture is empty"); + anyhow::ensure!( + addition_tolerance.is_finite() && addition_tolerance >= 0.0, + "invalid addition tolerance" + ); + let compression = CompressionOptions { + method: CompressionMethod::SVD, + tolerance: addition_tolerance, + max_bond_dim: None, + normalize_error: true, + }; + let mut level = self + .weights + .iter() + .zip(&self.quad) + .zip(&self.centers) + .map(|((&weight, &quad), ¢er)| { + rotated_gaussian_qtt( + r, + box_l, + center, + quad, + weight, + polynomial_degree, + interpolation_tolerance, + ) + }) + .collect::>>()?; + while level.len() > 1 { + let mut next = Vec::with_capacity(level.len().div_ceil(2)); + let mut terms = level.into_iter(); + while let Some(left) = terms.next() { + if let Some(right) = terms.next() { + let mut sum = left.add(&right)?; + sum.compress(&compression)?; + next.push(sum); + } else { + next.push(left); } } - tensor4_from_data(data, fused.left_dim(), 2, 2, fused.right_dim()) - .map_err(anyhow::Error::from) - }) - .collect::>>()?; - MPO::new(tensors).map_err(anyhow::Error::from) + level = next; + } + level + .pop() + .ok_or_else(|| anyhow::anyhow!("balanced Gaussian sum is empty")) + } + + /// Construct the same interpolative mixture as a quantics MPO. + pub fn to_interpolative_mpo( + &self, + r: usize, + box_l: f64, + polynomial_degree: usize, + interpolation_tolerance: f64, + addition_tolerance: f64, + ) -> anyhow::Result> { + fused_qtt_to_mpo(&self.to_interpolative_qtt( + r, + box_l, + polynomial_degree, + interpolation_tolerance, + addition_tolerance, + )?) + } +} + +impl Field2D for AnisoMixture2D { + fn eval(&self, x: f64, y: f64) -> f64 { + AnisoMixture2D::eval(self, x, y) + } } fn rotated_gaussian_qtt( @@ -128,10 +202,16 @@ fn rotated_gaussian_qtt( let lambda_major = 0.5 * (a + c - discriminant); let lambda_minor = 0.5 * (a + c + discriminant); anyhow::ensure!( - lambda_major.is_finite() && lambda_major > 0.0 && lambda_minor.is_finite(), + lambda_major.is_finite() + && lambda_major > 0.0 + && lambda_minor.is_finite() + && lambda_minor >= lambda_major, "Gaussian quadratic form is not positive definite" ); - anyhow::ensure!(weight.is_finite(), "invalid Gaussian weight"); + anyhow::ensure!( + weight.is_finite() && weight >= 0.0, + "invalid Gaussian weight" + ); anyhow::ensure!( tolerance.is_finite() && tolerance >= 0.0, "invalid interpolation tolerance" @@ -149,16 +229,15 @@ fn rotated_gaussian_qtt( major.1 /= norm; let sigma_major = (2.0 * lambda_major).sqrt().recip(); let sigma_minor = (2.0 * lambda_minor).sqrt().recip(); - let unsafe_spacing = 0.5 * sigma_minor; - let n = (4.0 * sigma_major / unsafe_spacing).ceil() as isize; - let cusp_locations = (-n..=n) + let spacing = 0.5 * sigma_minor; + let extent = (4.0 * sigma_major / spacing).ceil() as isize; + let unsafe_points = (-extent..=extent) .filter_map(|i| { - let distance = i as f64 * unsafe_spacing; + let distance = i as f64 * spacing; let point = [center.0 + distance * major.0, center.1 + distance * major.1]; (point[0].abs() < box_l && point[1].abs() < box_l).then(|| point.to_vec()) }) .collect::>(); - let options = InterpolativeQttOptions::default().with_tolerance(tolerance); interpolate_multi_scale_nd( |xy| { let (dx, dy) = (xy[0] - center.0, xy[1] - center.1); @@ -168,13 +247,14 @@ fn rotated_gaussian_qtt( &[box_l, box_l], r, polynomial_degree, - &cusp_locations, - &options, + &unsafe_points, + &InterpolativeQttOptions::default().with_tolerance(tolerance), ) .map_err(anyhow::Error::from) } -fn fused_qtt_to_mpo(qtt: &SimpleTensorTrain) -> anyhow::Result> { +/// Convert a fused site-dimension-4 QTT to a two-index-per-site MPO. +pub fn fused_qtt_to_mpo(qtt: &SimpleTensorTrain) -> anyhow::Result> { let tensors = qtt .site_tensors() .iter() @@ -197,383 +277,12 @@ fn fused_qtt_to_mpo(qtt: &SimpleTensorTrain) -> anyhow::Result> { MPO::new(tensors).map_err(anyhow::Error::from) } -/// Construct one rotated anisotropic Gaussian as a multiscale quantics MPO. -/// -/// Unsafe interpolation points are spaced by half the minor-axis standard -/// deviation along the major axis through the center. This keeps every box -/// intersecting the narrow ridge refined without making the entire 2D box unsafe. -/// `r` must be large enough to resolve the minor width. -pub fn rotated_gaussian_mpo( - r: usize, - box_l: f64, - center: (f64, f64), - quad: (f64, f64, f64), - weight: f64, - polynomial_degree: usize, - tolerance: f64, -) -> anyhow::Result> { - fused_qtt_to_mpo(&rotated_gaussian_qtt( - r, - box_l, - center, - quad, - weight, - polynomial_degree, - tolerance, - )?) -} - -/// A sum of isotropic 2D Gaussians `w_i exp(-a_i ((x-cx_i)^2 + (y-cy_i)^2))`. -#[derive(Clone, Debug)] -pub struct GaussianMixture2D { - /// Prefactors `w_i`. - pub weights: Vec, - /// Inverse widths `a_i`. - pub alphas: Vec, - /// Centers `(cx_i, cy_i)`. - pub centers: Vec<(f64, f64)>, -} - -impl GaussianMixture2D { - /// Draw `n` Gaussians: centers uniform in `[-L/2, L/2]^2` (kept away from the - /// box edge so tail truncation stays small), weights `U[0.5, 1.5]`, alphas - /// log-uniform in `alpha_range`. - pub fn random(n: usize, box_l: f64, alpha_range: (f64, f64), seed: u64) -> Self { - let mut rng = ChaCha8Rng::seed_from_u64(seed); - let half = box_l / 2.0; - let (a_lo, a_hi) = alpha_range; - let mut weights = Vec::with_capacity(n); - let mut alphas = Vec::with_capacity(n); - let mut centers = Vec::with_capacity(n); - for _ in 0..n { - weights.push(rng.random_range(0.5..1.5)); - alphas.push(rng.random_range(a_lo.ln()..a_hi.ln()).exp()); - centers.push((rng.random_range(-half..half), rng.random_range(-half..half))); - } - Self { - weights, - alphas, - centers, - } - } - - /// Evaluate the mixture at `(x, y)`. - pub fn eval(&self, x: f64, y: f64) -> f64 { - (0..self.weights.len()) - .map(|i| { - let (cx, cy) = self.centers[i]; - self.weights[i] * (-self.alphas[i] * ((x - cx).powi(2) + (y - cy).powi(2))).exp() - }) - .sum() - } -} - -impl Field2D for GaussianMixture2D { - fn eval(&self, x: f64, y: f64) -> f64 { - GaussianMixture2D::eval(self, x, y) - } -} - -/// A sum of anisotropic 2D Gaussians: narrow spikes of a fixed minor width, each -/// one stretched by its own aspect ratio along its own random direction. -/// -/// Spike `i` is `w_i exp(-(a_i dx^2 + 2 b_i dx dy + c_i dy^2))` with -/// `dx = x - cx_i`, `dy = y - cy_i`, and the quadratic form obtained by rotating -/// `diag(a_major, a_minor)` by the orientation angle, where -/// `a_minor = 1 / (2 sigma^2)` fixes the minor width and -/// `a_major = a_minor / rho^2` stretches the spike by `rho` along the major axis. -/// -/// This is the family case 5 defaults to. Measured at the case-5 settings its -/// global quantics rank grows like `N^0.5` and reaches the geometric bound of the -/// bit count at `N` = 1024, which is what makes it the family where a global -/// representation runs out of room and a patched one, held at its per-patch cap by -/// construction, has something to win. -/// -/// The per-spike orientation and aspect ratio are drawn so that the family is not -/// a pure shift family, which a mixture of one common shape would be: a low -/// dimensional manifold, and the degenerate case a compression study should not -/// rest on. They are not what makes the rank grow, though. Setting `rho_max = 1` -/// gives exactly that common-shape control, and measured at the same settings its -/// rank grows the same way, so the growth comes from the density of narrow spikes. -#[derive(Clone, Debug)] -pub struct AnisoMixture2D { - /// Prefactors `w_i`. - pub weights: Vec, - /// Quadratic forms `(a_i, b_i, c_i)` of `a dx^2 + 2 b dx dy + c dy^2`. - pub quad: Vec<(f64, f64, f64)>, - /// Centers `(cx_i, cy_i)`. - pub centers: Vec<(f64, f64)>, -} - -impl AnisoMixture2D { - /// Construct this mixture by adding individually interpolated Gaussian QTTs. - /// - /// The sum is SVD-compressed after every addition with the supplied relative - /// per-bond tolerance; the benchmark records this separately from its final - /// global relative-L2 truncation. - pub fn to_multiscale_mpo( - &self, - r: usize, - box_l: f64, - polynomial_degree: usize, - interpolation_tolerance: f64, - addition_tolerance: f64, - ) -> anyhow::Result> { - anyhow::ensure!( - self.weights.len() == self.quad.len() && self.weights.len() == self.centers.len(), - "anisotropic mixture arrays have different lengths" - ); - anyhow::ensure!(!self.weights.is_empty(), "anisotropic mixture is empty"); - anyhow::ensure!( - addition_tolerance.is_finite() && addition_tolerance >= 0.0, - "invalid addition tolerance" - ); - let compression = CompressionOptions { - method: CompressionMethod::SVD, - tolerance: addition_tolerance, - max_bond_dim: None, - normalize_error: true, - }; - let mut sum = rotated_gaussian_qtt( - r, - box_l, - self.centers[0], - self.quad[0], - self.weights[0], - polynomial_degree, - interpolation_tolerance, - )?; - for i in 1..self.weights.len() { - sum = sum.add(&rotated_gaussian_qtt( - r, - box_l, - self.centers[i], - self.quad[i], - self.weights[i], - polynomial_degree, - interpolation_tolerance, - )?)?; - sum.compress(&compression)?; - } - fused_qtt_to_mpo(&sum) - } - - /// Draw `n` anisotropic spikes on the box `[-box_l, box_l)^2`. - /// - /// Weights are `U[0.5, 1.5]`, the aspect ratio `rho` is log-uniform in - /// `[1, rho_max]`, the orientation is uniform in `[0, pi)` and the centers are - /// uniform in `0.9 * box_l`, kept off the box edge so tail truncation stays - /// small. The draw order is weight, rho, theta, center, per spike, and it is - /// part of the instance definition: the stream is a single `ChaCha8` sequence, - /// so reordering the draws would silently change every instance. - pub fn random(n: usize, box_l: f64, sigma_minor: f64, rho_max: f64, seed: u64) -> Self { - let mut rng = ChaCha8Rng::seed_from_u64(seed); - let half = 0.9 * box_l; - let a_minor = 1.0 / (2.0 * sigma_minor * sigma_minor); - let mut weights = Vec::with_capacity(n); - let mut quad = Vec::with_capacity(n); - let mut centers = Vec::with_capacity(n); - for _ in 0..n { - weights.push(rng.random_range(0.5..1.5)); - // Log-uniform in [1, rho_max], written as a power rather than as - // `exp(U[0, ln rho_max])` so that `rho_max = 1` is a legal setting: it - // gives the isotropic control family, spikes of a common shape, which - // is the comparison that shows the rank growth comes from the density - // of narrow spikes and not from the anisotropy. An empty range would - // panic instead. - let rho = rho_max.powf(rng.random_range(0.0..1.0)); - let theta = rng.random_range(0.0..std::f64::consts::PI); - let a_major = a_minor / (rho * rho); - let (s, c) = theta.sin_cos(); - // Rotate diag(a_major, a_minor) into the coordinate axes: the major - // axis of the spike points along theta and carries the smaller - // quadratic coefficient, so the spike is rho times longer there. - quad.push(( - a_major * c * c + a_minor * s * s, - (a_major - a_minor) * s * c, - a_major * s * s + a_minor * c * c, - )); - centers.push((rng.random_range(-half..half), rng.random_range(-half..half))); - } - Self { - weights, - quad, - centers, - } - } - - /// Evaluate the mixture at `(x, y)`. - pub fn eval(&self, x: f64, y: f64) -> f64 { - (0..self.weights.len()) - .map(|i| { - let (cx, cy) = self.centers[i]; - let (a, b, c) = self.quad[i]; - let (dx, dy) = (x - cx, y - cy); - self.weights[i] * (-(a * dx * dx + 2.0 * b * dx * dy + c * dy * dy)).exp() - }) - .sum() - } - - /// First derivatives with respect to the first and second coordinates. - pub fn gradient(&self, x: f64, y: f64) -> (f64, f64) { - (0..self.weights.len()).fold((0.0, 0.0), |(gx, gy), i| { - let (cx, cy) = self.centers[i]; - let (a, b, c) = self.quad[i]; - let (dx, dy) = (x - cx, y - cy); - let value = self.weights[i] * (-(a * dx * dx + 2.0 * b * dx * dy + c * dy * dy)).exp(); - ( - gx - 2.0 * (a * dx + b * dy) * value, - gy - 2.0 * (b * dx + c * dy) * value, - ) - }) - } -} - -impl Field2D for AnisoMixture2D { - fn eval(&self, x: f64, y: f64) -> f64 { - AnisoMixture2D::eval(self, x, y) - } -} - -/// Spatially indexed evaluator with a rigorous global absolute tail bound. -/// -/// Components whose center is farther than their major-axis cutoff radius are -/// omitted. The common exponent threshold is chosen so the sum of all omitted -/// positive Gaussian tails is at most `absolute_tolerance` at every point. -#[derive(Clone, Debug)] -pub struct LocalizedAnisoField { - mixture: AnisoMixture2D, - absolute_tolerance: f64, - bin_width: f64, - cutoff_squared: Vec, - bins: HashMap<(i64, i64), Vec>, -} - -impl LocalizedAnisoField { - /// Build a spatial index without changing the underlying random mixture. - pub fn new(mixture: AnisoMixture2D, absolute_tolerance: f64) -> anyhow::Result { - anyhow::ensure!( - absolute_tolerance.is_finite() && absolute_tolerance > 0.0, - "localized evaluator tolerance must be positive and finite" - ); - anyhow::ensure!( - mixture.weights.len() == mixture.quad.len() - && mixture.weights.len() == mixture.centers.len() - && !mixture.weights.is_empty(), - "invalid anisotropic mixture" - ); - anyhow::ensure!( - mixture - .weights - .iter() - .all(|weight| weight.is_finite() && *weight >= 0.0), - "localized evaluator requires finite non-negative weights" - ); - anyhow::ensure!( - mixture - .centers - .iter() - .all(|(x, y)| x.is_finite() && y.is_finite()), - "localized evaluator requires finite centers" - ); - let total_weight = mixture.weights.iter().sum::(); - anyhow::ensure!( - total_weight.is_finite() && total_weight > absolute_tolerance, - "localized evaluator tolerance must be smaller than total weight" - ); - let exponent_cutoff = (total_weight / absolute_tolerance).ln(); - let cutoff_squared = mixture - .quad - .iter() - .map(|&(a, b, c)| { - let discriminant = ((a - c).powi(2) + 4.0 * b * b).sqrt(); - let lambda_min = 0.5 * (a + c - discriminant); - anyhow::ensure!(lambda_min.is_finite() && lambda_min > 0.0); - Ok(exponent_cutoff / lambda_min) - }) - .collect::>>()?; - let bin_width = cutoff_squared - .iter() - .copied() - .fold(0.0_f64, f64::max) - .sqrt(); - let mut bins = HashMap::<(i64, i64), Vec>::new(); - for (i, &(x, y)) in mixture.centers.iter().enumerate() { - bins.entry(Self::bin_key(x, y, bin_width)) - .or_default() - .push(i); - } - Ok(Self { - mixture, - absolute_tolerance, - bin_width, - cutoff_squared, - bins, - }) - } - - fn bin_key(x: f64, y: f64, bin_width: f64) -> (i64, i64) { - ( - (x / bin_width).floor() as i64, - (y / bin_width).floor() as i64, - ) - } - - /// Guaranteed pointwise absolute error bound relative to exact evaluation. - pub fn absolute_tolerance(&self) -> f64 { - self.absolute_tolerance - } - - /// Evaluate using only components whose tail can exceed the global budget. - pub fn eval(&self, x: f64, y: f64) -> f64 { - let (bx, by) = Self::bin_key(x, y, self.bin_width); - let mut value = 0.0; - for dx_bin in -1..=1 { - for dy_bin in -1..=1 { - if let Some(indices) = self.bins.get(&(bx + dx_bin, by + dy_bin)) { - for &i in indices { - let (cx, cy) = self.mixture.centers[i]; - let (dx, dy) = (x - cx, y - cy); - if dx * dx + dy * dy <= self.cutoff_squared[i] { - let (a, b, c) = self.mixture.quad[i]; - value += self.mixture.weights[i] - * (-(a * dx * dx + 2.0 * b * dx * dy + c * dy * dy)).exp(); - } - } - } - } - } - value - } -} - -impl Field2D for LocalizedAnisoField { - fn eval(&self, x: f64, y: f64) -> f64 { - LocalizedAnisoField::eval(self, x, y) - } -} - -/// Closed form of `int f(x,y) g(y,z) dy` over the whole real line. -pub fn analytic_contraction(f: &GaussianMixture2D, g: &GaussianMixture2D, x: f64, z: f64) -> f64 { - let mut s = 0.0; - for i in 0..f.weights.len() { - let (fcx, fcy) = f.centers[i]; - let a = f.alphas[i]; - let fx = f.weights[i] * (-a * (x - fcx).powi(2)).exp(); - for j in 0..g.weights.len() { - let (gcy, gcz) = g.centers[j]; - let b = g.alphas[j]; - let gz = g.weights[j] * (-b * (z - gcz).powi(2)).exp(); - let ab = a + b; - let yfac = - (std::f64::consts::PI / ab).sqrt() * (-(a * b / ab) * (fcy - gcy).powi(2)).exp(); - s += fx * gz * yfac; - } - } - s +/// Coordinate of grid index `i` on the half-open interval `[-box_l, box_l)`. +pub fn grid_coord(i: u64, r: usize, box_l: f64) -> f64 { + -box_l + i as f64 * (2.0 * box_l / (1u64 << r) as f64) } -/// Closed form of `int f(x,y) g(y,z) dy` for anisotropic mixtures. +/// Closed form of the infinite-domain contraction `int f(x,y) g(y,z) dy`. pub fn analytic_contraction_aniso(f: &AnisoMixture2D, g: &AnisoMixture2D, x: f64, z: f64) -> f64 { analytic_contraction_aniso_with(f, g, x, z, |quadratic, linear, constant| { (std::f64::consts::PI / quadratic).sqrt() @@ -650,346 +359,72 @@ fn analytic_contraction_aniso_with( sum } -/// Coordinate of grid index `i`: `-L + i * 2L/2^R` (the grid is `[-L, L)`). -pub fn grid_coord(i: u64, r: usize, box_l: f64) -> f64 { - let step = 2.0 * box_l / (1u64 << r) as f64; - -box_l + i as f64 * step -} - -/// Cross-interpolate `mix` into a fused 2D quantics TT on `[-L, L)^2` with `r` -/// bits per variable. Returns the TT (site dim 4 per site) and the grid step. -pub fn to_quantics_fused_tt( - mix: &GaussianMixture2D, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, -) -> anyhow::Result<(SimpleTensorTrain, f64)> { - to_quantics_fused_tt_field(mix, r, box_l, tol, max_bond) -} - -/// [`to_quantics_fused_tt`] for any [`Field2D`], which is the one case-5 uses so -/// that its two instance families share a single construction. The grid, the -/// unfolding scheme and the `QtciOptions` are identical, so a train built here is -/// the same object the typed entry point returns. -pub fn to_quantics_fused_tt_field( - mix: &M, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, -) -> anyhow::Result<(SimpleTensorTrain, f64)> { - to_quantics_fused_tt_field_with_pivots(mix, r, box_l, tol, max_bond, None) -} - -fn to_quantics_fused_tt_field_with_pivots( - mix: &M, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, - initial_pivots: Option>>, -) -> anyhow::Result<(SimpleTensorTrain, f64)> { - let grid = DiscretizedGrid::builder(&[r, r]) - .with_lower_bound(&[-box_l, -box_l]) - .with_upper_bound(&[box_l, box_l]) - .with_unfolding_scheme(UnfoldingScheme::Fused) - .build()?; - let m = mix.clone(); - let mut opts = QtciOptions::default() - .with_tolerance(tol) - .with_max_bond_dim(max_bond) - .with_unfoldingscheme(UnfoldingScheme::Fused); - if initial_pivots.is_some() { - opts = opts.with_nrandominitpivot(0); - } - let (qtci, _ranks, _errs) = quanticscrossinterpolate( - &grid, - move |xy: &[f64]| m.eval(xy[0], xy[1]), - initial_pivots, - opts, - )?; - let step = 2.0 * box_l / (1u64 << r) as f64; - Ok((qtci.tensor_train(), step)) -} - -/// `f(v1, v2)` as a quantics MPO: site `n` carries (bit `n` of `v1`, bit `n` of -/// `v2`), most significant bit first, `r` sites. Returns `(mpo, grid_step)`. -pub fn to_quantics_mpo( - mix: &GaussianMixture2D, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, -) -> anyhow::Result<(MPO, f64)> { - to_quantics_mpo_field(mix, r, box_l, tol, max_bond) -} - -/// [`to_quantics_mpo`] for any [`Field2D`]. -pub fn to_quantics_mpo_field( - mix: &M, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, -) -> anyhow::Result<(MPO, f64)> { - let (tt, step) = to_quantics_fused_tt_field(mix, r, box_l, tol, max_bond)?; - Ok((fused_qtt_to_mpo(&tt)?, step)) -} - -/// Deterministic [`to_quantics_mpo_field`] variant using explicit zero-based grid pivots. -/// -/// Random initial pivots are disabled when this entry point is used, so identical -/// inputs and pivots produce cacheable input tensors. -pub fn to_quantics_mpo_field_with_pivots( - mix: &M, - r: usize, - box_l: f64, - tol: f64, - max_bond: usize, - initial_pivots: Vec>, -) -> anyhow::Result<(MPO, f64)> { - anyhow::ensure!(!initial_pivots.is_empty(), "initial pivot list is empty"); - let (tt, step) = - to_quantics_fused_tt_field_with_pivots(mix, r, box_l, tol, max_bond, Some(initial_pivots))?; - Ok((fused_qtt_to_mpo(&tt)?, step)) -} - #[cfg(test)] mod tests { use super::*; use crate::harness::index_to_bits; - fn quadrature(f: impl Fn(f64) -> f64, lo: f64, hi: f64, intervals: usize) -> f64 { - let step = (hi - lo) / intervals as f64; - (0..=intervals) - .map(|i| { - let weight = if i == 0 || i == intervals { 0.5 } else { 1.0 }; - weight * f(lo + i as f64 * step) * step - }) - .sum() - } - - #[test] - fn multiscale_axis_aligned_gaussian_mpo_matches_grid_values() { - let (r, box_l) = (8, 1.0); - let center = (0.17, -0.23); - let alpha = (8.0, 20.0); - let weight = 1.3; - let mpo = axis_aligned_gaussian_mpo(r, box_l, center, alpha, weight, 12, 1e-12).unwrap(); - let step = 2.0 * box_l / (1usize << r) as f64; - for (ix, iy) in [(0, 0), (23, 197), (128, 128), (150, 98), (255, 255)] { - let x = -box_l + ix as f64 * step; - let y = -box_l + iy as f64 * step; - let indices = index_to_bits(ix, r) - .into_iter() - .zip(index_to_bits(iy, r)) - .flat_map(|(x_bit, y_bit)| [x_bit, y_bit]) - .collect::>(); - let got = mpo.evaluate(&indices).unwrap(); - let expected = weight - * (-alpha.0 * (x - center.0).powi(2) - alpha.1 * (y - center.1).powi(2)).exp(); - assert!( - (got - expected).abs() < 2e-8, - "({x}, {y}): {got} != {expected}" - ); - } - } - - #[test] - fn multiscale_gaussian_mpo_stays_accurate_as_r_increases() { - let box_l = 1.0; - let center = (0.173, -0.227); - let alpha = (32.0, 200.0); - let weight = 1.3; - let sigma_min = 1.0 / (2.0_f64 * alpha.1).sqrt(); - - for r in [8, 10, 12] { - let step = 2.0 * box_l / (1usize << r) as f64; - assert!( - step <= sigma_min / 4.0, - "R={r} does not resolve the narrow width" - ); - let mpo = - axis_aligned_gaussian_mpo(r, box_l, center, alpha, weight, 24, 1e-12).unwrap(); - let grid_size = 1usize << r; - let mut max_error = 0.0_f64; - for sample in 0..128 { - let ix = (73 * sample + 11) % grid_size; - let iy = (151 * sample + 29) % grid_size; - let x = -box_l + ix as f64 * step; - let y = -box_l + iy as f64 * step; - let indices = index_to_bits(ix as u64, r) - .into_iter() - .zip(index_to_bits(iy as u64, r)) - .flat_map(|(x_bit, y_bit)| [x_bit, y_bit]) - .collect::>(); - let got = mpo.evaluate(&indices).unwrap(); - let expected = weight - * (-alpha.0 * (x - center.0).powi(2) - alpha.1 * (y - center.1).powi(2)).exp(); - max_error = max_error.max((got - expected).abs()); - } - eprintln!("R={r} rank={} max_error={max_error:.3e}", mpo.rank()); - assert!( - max_error < 5e-8, - "R={r}, rank={}, max error={max_error:.3e}", - mpo.rank() - ); - assert!( - mpo.rank() <= 400, - "R={r} unexpectedly increased rank to {}", - mpo.rank() - ); - } + fn fused_point(ix: u64, iy: u64, r: usize) -> Vec { + index_to_bits(ix, r) + .into_iter() + .zip(index_to_bits(iy, r)) + .map(|(x, y)| x + 2 * y) + .collect() } #[test] - fn multiscale_rotated_gaussian_mpo_resolves_a_narrow_ridge() { + fn rotated_gaussian_interpolation_resolves_a_narrow_ridge() { let (r, box_l) = (10, 1.0); let center = (0.07, -0.09); - let (sigma_minor, rho, angle) = (0.05_f64, 8.0_f64, std::f64::consts::FRAC_PI_4); - let lambda_minor = 1.0 / (2.0 * sigma_minor.powi(2)); - let lambda_major = lambda_minor / rho.powi(2); + let (sigma, rho, angle) = (0.05_f64, 8.0_f64, std::f64::consts::FRAC_PI_4); + let minor = 1.0 / (2.0 * sigma.powi(2)); + let major = minor / rho.powi(2); let (sin, cos) = angle.sin_cos(); let quad = ( - lambda_major * cos * cos + lambda_minor * sin * sin, - (lambda_major - lambda_minor) * sin * cos, - lambda_major * sin * sin + lambda_minor * cos * cos, + major * cos * cos + minor * sin * sin, + (major - minor) * sin * cos, + major * sin * sin + minor * cos * cos, ); - let mpo = rotated_gaussian_mpo(r, box_l, center, quad, 1.3, 28, 1e-12).unwrap(); + let qtt = rotated_gaussian_qtt(r, box_l, center, quad, 1.3, 28, 1e-12).unwrap(); let step = 2.0 * box_l / (1usize << r) as f64; let mut max_error = 0.0_f64; - { - let mut check_point = |ix: usize, iy: usize| { - let x = -box_l + ix as f64 * step; - let y = -box_l + iy as f64 * step; - let indices = index_to_bits(ix as u64, r) - .into_iter() - .zip(index_to_bits(iy as u64, r)) - .flat_map(|(x_bit, y_bit)| [x_bit, y_bit]) - .collect::>(); - let got = mpo.evaluate(&indices).unwrap(); - let (dx, dy) = (x - center.0, y - center.1); - let expected = - 1.3 * (-(quad.0 * dx * dx + 2.0 * quad.1 * dx * dy + quad.2 * dy * dy)).exp(); - max_error = max_error.max((got - expected).abs()); - }; - for sample in 0..256 { - check_point( - (73 * sample + 11) % (1usize << r), - (151 * sample + 29) % (1usize << r), - ); - } - for major_step in -6..=6 { - for minor_step in -4..=4 { - let u = major_step as f64 * 0.5 * sigma_minor * rho; - let v = minor_step as f64 * 0.5 * sigma_minor; - let x = center.0 + cos * u - sin * v; - let y = center.1 + sin * u + cos * v; - let ix = ((x + box_l) / step).round() as usize; - let iy = ((y + box_l) / step).round() as usize; - check_point(ix.min((1usize << r) - 1), iy.min((1usize << r) - 1)); - } - } + for sample in 0..256 { + let ix = ((73 * sample + 11) % (1usize << r)) as u64; + let iy = ((151 * sample + 29) % (1usize << r)) as u64; + let x = grid_coord(ix, r, box_l); + let y = grid_coord(iy, r, box_l); + let (dx, dy) = (x - center.0, y - center.1); + let expected = + 1.3 * (-(quad.0 * dx * dx + 2.0 * quad.1 * dx * dy + quad.2 * dy * dy)).exp(); + max_error = + max_error.max((qtt.evaluate(&fused_point(ix, iy, r)).unwrap() - expected).abs()); } - eprintln!("rotated rank={} max_error={max_error:.3e}", mpo.rank()); assert!( max_error < 5e-8, - "rank={}, max error={max_error:.3e}", - mpo.rank() + "rank={}, error={max_error:.3e}", + qtt.rank() ); + assert!(step <= sigma / 4.0); } #[test] - fn multiscale_anisotropic_mixture_matches_grid_values() { + fn balanced_interpolative_sum_matches_the_mixture() { let (r, box_l) = (8, 1.0); - let mixture = AnisoMixture2D::random(2, 0.7, 0.08, 3.0, 17); - let mpo = mixture - .to_multiscale_mpo(r, box_l, 24, 1e-12, 1e-10) + let mixture = AnisoMixture2D::random(5, 0.7, 0.08, 3.0, 17); + let qtt = mixture + .to_interpolative_qtt(r, box_l, 24, 1e-12, 1e-10) .unwrap(); - let step = 2.0 * box_l / (1usize << r) as f64; - let mut max_error = 0.0_f64; + let mut squared_error = 0.0; + let mut squared_reference = 0.0; for sample in 0..128 { - let ix = (73 * sample + 11) % (1usize << r); - let iy = (151 * sample + 29) % (1usize << r); - let x = -box_l + ix as f64 * step; - let y = -box_l + iy as f64 * step; - let indices = index_to_bits(ix as u64, r) - .into_iter() - .zip(index_to_bits(iy as u64, r)) - .flat_map(|(x_bit, y_bit)| [x_bit, y_bit]) - .collect::>(); - max_error = max_error.max((mpo.evaluate(&indices).unwrap() - mixture.eval(x, y)).abs()); - } - assert!( - max_error < 1e-7, - "rank={}, max error={max_error:.3e}", - mpo.rank() - ); - } - - #[test] - fn localized_anisotropic_evaluator_respects_absolute_tail_bound() { - let mixture = AnisoMixture2D::random(512, 4.0, 0.05, 8.0, 23); - let localized = LocalizedAnisoField::new(mixture.clone(), 1e-10).unwrap(); - assert_eq!(localized.absolute_tolerance(), 1e-10); - for sample in 0..256 { - let x = -5.0 + 10.0 * ((73 * sample + 11) % 257) as f64 / 256.0; - let y = -5.0 + 10.0 * ((151 * sample + 29) % 257) as f64 / 256.0; - let error = (localized.eval(x, y) - mixture.eval(x, y)).abs(); - assert!(error <= 1e-10, "({x}, {y}): error={error:.3e}"); + let ix = ((73 * sample + 11) % (1usize << r)) as u64; + let iy = ((151 * sample + 29) % (1usize << r)) as u64; + let expected = mixture.eval(grid_coord(ix, r, box_l), grid_coord(iy, r, box_l)); + let error = qtt.evaluate(&fused_point(ix, iy, r)).unwrap() - expected; + squared_error += error * error; + squared_reference += expected * expected; } - } - - #[test] - fn explicit_tci_pivots_make_input_construction_deterministic() { - let mixture = AnisoMixture2D::random(4, 1.0, 0.1, 3.0, 29); - let pivots = vec![vec![16, 16], vec![8, 24], vec![24, 8]]; - let (first, _) = - to_quantics_mpo_field_with_pivots(&mixture, 5, 1.0, 1e-8, 64, pivots.clone()).unwrap(); - let (second, _) = - to_quantics_mpo_field_with_pivots(&mixture, 5, 1.0, 1e-8, 64, pivots).unwrap(); - assert_eq!(first.rank(), second.rank()); - for (left, right) in first.site_tensors().iter().zip(second.site_tensors()) { - assert_eq!(left.to_col_major_vec(), right.to_col_major_vec()); - } - } - - #[test] - fn localized_anisotropic_evaluator_rejects_negative_weights() { - let mut mixture = AnisoMixture2D::random(1, 1.0, 0.05, 8.0, 23); - mixture.weights[0] = -1.0; - assert!(LocalizedAnisoField::new(mixture, 1e-10).is_err()); - } - - #[test] - fn analytic_contraction_matches_quadrature() { - let f = GaussianMixture2D::random(3, 4.0, (0.5, 2.0), 1); - let g = GaussianMixture2D::random(2, 4.0, (0.5, 2.0), 2); - let (x, z) = (0.3, -0.7); - let numeric = quadrature(|y| f.eval(x, y) * g.eval(y, z), -8.0, 8.0, 20_000); - let analytic = analytic_contraction(&f, &g, x, z); - assert!((numeric - analytic).abs() < 1e-8 * analytic.abs().max(1.0)); - } - - #[test] - fn anisotropic_analytic_contraction_matches_quadrature() { - let f = AnisoMixture2D::random(3, 4.0, 0.3, 4.0, 1); - let g = AnisoMixture2D::random(2, 4.0, 0.3, 4.0, 2); - let (x, z) = (0.3, -0.7); - let numeric = quadrature(|y| f.eval(x, y) * g.eval(y, z), -12.0, 12.0, 40_000); - let analytic = analytic_contraction_aniso(&f, &g, x, z); - assert!((numeric - analytic).abs() < 1e-8 * analytic.abs().max(1.0)); - } - - #[test] - fn bounded_anisotropic_contraction_matches_quadrature() { - let f = AnisoMixture2D::random(3, 1.0, 0.3, 4.0, 1); - let g = AnisoMixture2D::random(2, 1.0, 0.3, 4.0, 2); - let (x, z, box_l) = (0.3, -0.7, 1.0); - let numeric = quadrature(|y| f.eval(x, y) * g.eval(y, z), -box_l, box_l, 40_000); - let analytic = analytic_contraction_aniso_box(&f, &g, x, z, box_l); - assert!((numeric - analytic).abs() < 1e-8 * analytic.abs().max(1.0)); + assert!((squared_error / squared_reference).sqrt() < 1e-7); } #[test] @@ -999,101 +434,31 @@ mod tests { let (x, z, r, box_l) = (0.3, -0.7, 10, 1.0); let step = 2.0 * box_l / (1u64 << r) as f64; let direct = (0..1u64 << r) - .map(|i| { - let y = -box_l + i as f64 * step; - f.eval(x, y) * g.eval(y, z) * step - }) + .map(|i| f.eval(x, grid_coord(i, r, box_l)) * g.eval(grid_coord(i, r, box_l), z) * step) .sum::(); let reference = discrete_contraction_aniso_reference(&f, &g, x, z, r, box_l); assert!((direct - reference).abs() < 1e-10 * direct.abs().max(1.0)); } - /// The rotated quadratic form, against a value computed by hand. - /// - /// One spike at the origin with `a_minor = 2`, `a_major = 0.5` (so `rho = 2`) - /// rotated by 45 degrees: `a = c = 1.25` and `b = -0.75`. The point `(1, 1)` - /// lies on the major axis at `u = sqrt(2)`, so the exponent is - /// `a_major u^2 = 1`, and the point `(1, -1)` lies on the minor axis at - /// `v = sqrt(2)`, where the exponent is `a_minor v^2 = 4`. #[test] - fn aniso_eval_matches_a_hand_computed_rotated_form() { - let mix = AnisoMixture2D { - weights: vec![2.0], - quad: vec![(1.25, -0.75, 1.25)], - centers: vec![(0.0, 0.0)], - }; - let major = mix.eval(1.0, 1.0); - let minor = mix.eval(1.0, -1.0); - assert!( - (major - 2.0 * (-1.0f64).exp()).abs() < 1e-14, - "along the major axis: {major}" - ); - assert!( - (minor - 2.0 * (-4.0f64).exp()).abs() < 1e-14, - "along the minor axis: {minor}" - ); - // The center is the maximum and carries the weight. - assert!((mix.eval(0.0, 0.0) - 2.0).abs() < 1e-14); - } - - /// `random` has to produce exactly that family: every drawn form is a rotation - /// of `diag(a_minor / rho^2, a_minor)` with `a_minor = 1 / (2 sigma^2)` and - /// `rho` in `[1, rho_max]`. Rotation leaves the trace and the determinant - /// alone, so the two eigenvalues are recoverable from the stored `(a, b, c)` - /// and can be checked against sigma and the aspect range without knowing the - /// angle. The draw is also required to be deterministic in the seed. - #[test] - fn aniso_random_draws_the_declared_family() { + fn random_draws_the_declared_anisotropic_family() { let (sigma, rho_max) = (0.05, 8.0); let mix = AnisoMixture2D::random(64, 1.0, sigma, rho_max, 7); assert_eq!( AnisoMixture2D::random(64, 1.0, sigma, rho_max, 7).quad, mix.quad ); - let a_minor = 1.0 / (2.0 * sigma * sigma); + let expected_minor = 1.0 / (2.0 * sigma * sigma); for (i, &(a, b, c)) in mix.quad.iter().enumerate() { - // Eigenvalues of [[a, b], [b, c]]. let mean = 0.5 * (a + c); let gap = (0.25 * (a - c).powi(2) + b * b).sqrt(); - let (lo, hi) = (mean - gap, mean + gap); + let rho = (expected_minor / (mean - gap)).sqrt(); assert!( - (hi - a_minor).abs() < 1e-9 * a_minor, - "spike {i}: minor {hi}" + (mean + gap - expected_minor).abs() < 1e-9 * expected_minor, + "term {i}" ); - let rho = (a_minor / lo).sqrt(); - assert!( - (1.0..=rho_max).contains(&rho), - "spike {i}: aspect {rho} outside [1, {rho_max}]" - ); - let (cx, cy) = mix.centers[i]; - assert!(cx.abs() <= 0.9 && cy.abs() <= 0.9); + assert!((1.0..=rho_max).contains(&rho), "term {i}: rho={rho}"); assert!((0.5..1.5).contains(&mix.weights[i])); } } - - #[test] - fn quantics_mpo_evaluates_to_function_values() { - let r = 8; - let l = 4.0; - let mix = GaussianMixture2D::random(3, l, (0.5, 2.0), 3); - let (mpo, _dy) = to_quantics_mpo(&mix, r, l, 1e-10, 200).unwrap(); - assert_eq!(mpo.len(), r); - for &(i, j) in &[(0u64, 0u64), (37, 200), (255, 1), (128, 128)] { - let x = grid_coord(i, r, l); - let y = grid_coord(j, r, l); - let xb = crate::harness::index_to_bits(i, r); - let yb = crate::harness::index_to_bits(j, r); - let mut idx = Vec::with_capacity(2 * r); - for n in 0..r { - idx.push(xb[n]); - idx.push(yb[n]); - } - let v = mpo.evaluate(&idx).unwrap(); - assert!( - (v - mix.eval(x, y)).abs() < 1e-6, - "at ({x},{y}): {v} vs {}", - mix.eval(x, y) - ); - } - } } diff --git a/src/gaussian_input.rs b/src/gaussian_input.rs new file mode 100644 index 0000000..04f2d10 --- /dev/null +++ b/src/gaussian_input.rs @@ -0,0 +1,294 @@ +//! Shared deterministic Gaussian inputs for the two Gaussian benchmark cases. + +use std::path::{Path, PathBuf}; +use std::time::{Duration, Instant}; + +use tensor4all_simplett::{ + AbstractTensorTrain, CompressionMethod, CompressionOptions, SimpleTensorTrain, Tensor3Ops, +}; + +use crate::gaussian::{grid_coord, AnisoMixture2D}; +use crate::harness::{index_to_bits, sample_grid_indices}; +use crate::hdf5_export::{load_tt_from_mps, save_tt_as_mps}; + +/// Fixed patch rank cap used by every patched benchmark arm. +pub const PATCH_CAP: usize = 128; +/// Final global relative-L2 input tolerance. +pub const INPUT_L2_RTOL: f64 = 1e-6; +const CACHE_SCHEMA: &str = "interpolative-gaussian-pair-v2"; +const TENSOR4ALL_REV: &str = "9e9aedaebe0d3918b34dd399ff0981e337f3835b"; + +/// Parameters that uniquely define one cached input pair. +#[derive(Clone, Debug)] +pub struct GaussianInputConfig { + pub n: usize, + pub sigma_minor: f64, + pub rho_max: f64, + pub spacing: f64, + pub polynomial_degree: usize, + pub interpolation_tolerance: f64, + pub addition_tolerance: f64, + pub seed: u64, + pub cache_dir: PathBuf, + pub refresh: bool, +} + +/// Prepared pair and complete untimed preparation metadata. +pub struct GaussianInputPair { + pub left: SimpleTensorTrain, + pub right: SimpleTensorTrain, + pub left_mixture: AnisoMixture2D, + pub right_mixture: AnisoMixture2D, + pub r: usize, + pub box_l: f64, + pub cache_key: String, + pub cache_hit: bool, + pub cache_load: Duration, + pub build: Duration, + pub compression: Duration, + pub raw_left_chi: usize, + pub raw_right_chi: usize, + pub raw_left_params: usize, + pub raw_right_params: usize, +} + +/// Choose the box and the smallest bit count resolving the minor width by eight cells. +pub fn box_and_bits(n: usize, sigma_minor: f64, spacing: f64) -> (f64, usize) { + let box_l = 0.5 * spacing * sigma_minor * (n as f64).sqrt(); + let mut r = 2; + while 2.0 * box_l / (1usize << r) as f64 > sigma_minor / 8.0 { + r += 1; + } + (box_l, r) +} + +/// Number of stored scalar entries in a tensor train. +pub fn tensortrain_n_params(tt: &SimpleTensorTrain) -> usize { + tt.site_tensors() + .iter() + .map(|core| core.left_dim() * core.site_dim() * core.right_dim()) + .sum() +} + +/// Load or build, then globally L2-compress, one deterministic Gaussian input pair. +pub fn prepare_gaussian_pair(config: &GaussianInputConfig) -> anyhow::Result { + anyhow::ensure!(config.n > 0, "Gaussian count must be positive"); + let (box_l, r) = box_and_bits(config.n, config.sigma_minor, config.spacing); + let left_mixture = AnisoMixture2D::random( + config.n, + box_l, + config.sigma_minor, + config.rho_max, + config.seed.wrapping_add(1), + ); + let right_mixture = AnisoMixture2D::random( + config.n, + box_l, + config.sigma_minor, + config.rho_max, + config.seed.wrapping_add(2), + ); + let cache_key = format!( + "{CACHE_SCHEMA}-rev{TENSOR4ALL_REV}-n{}-r{r}-sigma{:016x}-rho{:016x}-spacing{:016x}-degree{}-interp{:016x}-add{:016x}-seed{}", + config.n, + config.sigma_minor.to_bits(), + config.rho_max.to_bits(), + config.spacing.to_bits(), + config.polynomial_degree, + config.interpolation_tolerance.to_bits(), + config.addition_tolerance.to_bits(), + config.seed, + ); + std::fs::create_dir_all(&config.cache_dir)?; + let path = config.cache_dir.join(format!("{cache_key}.h5")); + let load_start = Instant::now(); + let (mut left, mut right, cache_hit, cache_load, build) = if path.exists() && !config.refresh { + let left = load_tt_from_mps(path_str(&path)?, "left")?; + let right = load_tt_from_mps(path_str(&path)?, "right")?; + validate_cached_pair(&left, &right, r)?; + (left, right, true, load_start.elapsed(), Duration::ZERO) + } else { + let build_start = Instant::now(); + let left = left_mixture.to_interpolative_qtt( + r, + box_l, + config.polynomial_degree, + config.interpolation_tolerance, + config.addition_tolerance, + )?; + let right = right_mixture.to_interpolative_qtt( + r, + box_l, + config.polynomial_degree, + config.interpolation_tolerance, + config.addition_tolerance, + )?; + validate_cached_pair(&left, &right, r)?; + write_pair_atomically(&path, &left, &right)?; + (left, right, false, Duration::ZERO, build_start.elapsed()) + }; + let raw_left_chi = left.rank(); + let raw_right_chi = right.rank(); + let raw_left_params = tensortrain_n_params(&left); + let raw_right_params = tensortrain_n_params(&right); + let compression_start = Instant::now(); + let options = CompressionOptions { + method: CompressionMethod::SVD, + tolerance: INPUT_L2_RTOL, + max_bond_dim: None, + normalize_error: true, + }; + left.compress(&options)?; + right.compress(&options)?; + let compression = compression_start.elapsed(); + Ok(GaussianInputPair { + left, + right, + left_mixture, + right_mixture, + r, + box_l, + cache_key, + cache_hit, + cache_load, + build, + compression, + raw_left_chi, + raw_right_chi, + raw_left_params, + raw_right_params, + }) +} + +/// Deterministic holdout estimate of the pair's common relative-L2 input error. +pub fn sampled_input_relative_l2( + pair: &GaussianInputPair, + samples: usize, + seed: u64, +) -> anyhow::Result<(f64, f64)> { + let mut left_error = 0.0; + let mut left_reference = 0.0; + let mut right_error = 0.0; + let mut right_reference = 0.0; + for index in sample_grid_indices(2 * pair.r, samples, seed) { + let mask = (1u64 << pair.r) - 1; + let ix = index >> pair.r; + let iy = index & mask; + let point: Vec<_> = index_to_bits(ix, pair.r) + .into_iter() + .zip(index_to_bits(iy, pair.r)) + .map(|(x, y)| x + 2 * y) + .collect(); + let x = grid_coord(ix, pair.r, pair.box_l); + let y = grid_coord(iy, pair.r, pair.box_l); + let expected_left = pair.left_mixture.eval(x, y); + let expected_right = pair.right_mixture.eval(x, y); + let delta_left = pair.left.evaluate(&point)? - expected_left; + let delta_right = pair.right.evaluate(&point)? - expected_right; + left_error += delta_left * delta_left; + left_reference += expected_left * expected_left; + right_error += delta_right * delta_right; + right_reference += expected_right * expected_right; + } + anyhow::ensure!( + left_reference > 0.0 && right_reference > 0.0, + "zero holdout reference norm" + ); + Ok(( + (left_error / left_reference).sqrt(), + (right_error / right_reference).sqrt(), + )) +} + +fn validate_cached_pair( + left: &SimpleTensorTrain, + right: &SimpleTensorTrain, + r: usize, +) -> anyhow::Result<()> { + anyhow::ensure!( + left.len() == r && right.len() == r, + "cached site count mismatch" + ); + anyhow::ensure!( + left.site_tensors().iter().all(|core| core.site_dim() == 4) + && right.site_tensors().iter().all(|core| core.site_dim() == 4), + "cached site dimension mismatch" + ); + Ok(()) +} + +fn write_pair_atomically( + path: &Path, + left: &SimpleTensorTrain, + right: &SimpleTensorTrain, +) -> anyhow::Result<()> { + let temporary = path.with_extension(format!("{}.tmp", std::process::id())); + let _ = std::fs::remove_file(&temporary); + save_tt_as_mps(path_str(&temporary)?, "left", left, false)?; + save_tt_as_mps(path_str(&temporary)?, "right", right, true)?; + std::fs::rename(&temporary, path)?; + Ok(()) +} + +fn path_str(path: &Path) -> anyhow::Result<&str> { + path.to_str() + .ok_or_else(|| anyhow::anyhow!("non-UTF-8 cache path: {path:?}")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cached_pair_round_trip_preserves_values_and_rank() { + let cache_dir = + std::env::temp_dir().join(format!("t4a-gaussian-cache-{}", std::process::id())); + let config = GaussianInputConfig { + n: 2, + sigma_minor: 0.12, + rho_max: 2.0, + spacing: 3.0, + polynomial_degree: 12, + interpolation_tolerance: 1e-9, + addition_tolerance: 1e-10, + seed: 31, + cache_dir: cache_dir.clone(), + refresh: true, + }; + let first = prepare_gaussian_pair(&config).unwrap(); + let second = prepare_gaussian_pair(&GaussianInputConfig { + refresh: false, + ..config + }) + .unwrap(); + assert!(!first.cache_hit); + assert!(second.cache_hit); + assert_eq!(first.raw_left_chi, second.raw_left_chi); + assert_eq!(first.raw_right_chi, second.raw_right_chi); + for point in [vec![0; first.r], (0..first.r).map(|i| i % 4).collect()] { + assert!( + (first.left.evaluate(&point).unwrap() - second.left.evaluate(&point).unwrap()) + .abs() + < 1e-12 + ); + } + let left_mpo = crate::gaussian::fused_qtt_to_mpo(&second.left).unwrap(); + let right_mpo = crate::gaussian::fused_qtt_to_mpo(&second.right).unwrap(); + let (left_train, right_train) = + crate::patched_mpo::mpo_pair_to_tensortrains(&left_mpo, &right_mpo).unwrap(); + for (left_sites, right_sites) in left_train + .site_indices() + .iter() + .zip(right_train.site_indices()) + { + assert_eq!( + left_sites + .iter() + .filter(|index| right_sites.contains(index)) + .count(), + 1 + ); + } + std::fs::remove_dir_all(cache_dir).unwrap(); + } +} diff --git a/src/hdf5_export.rs b/src/hdf5_export.rs index f8d4f41..76c5db0 100644 --- a/src/hdf5_export.rs +++ b/src/hdf5_export.rs @@ -35,6 +35,17 @@ where Ok(()) } +/// Load one HDF5 MPS group back into a simple tensor train. +pub fn load_tt_from_mps(path: &str, name: &str) -> anyhow::Result> +where + T: TTScalar + TensorElement + Clone, +{ + let tt = tensor4all_hdf5::load_mps(path, name)?; + Ok(tensor4all_treetn::treetn_to_tensor_train::( + tt.into_treetn(), + )?) +} + #[cfg(test)] mod tests { use super::*; @@ -43,28 +54,17 @@ mod tests { use num_complex::Complex64; use tensor4all_simplett::AbstractTensorTrain; - /// HDF5 `MPS` -> `itensorlike` -> `treetn` -> `simplett`, the inverse of - /// the export bridge, so the loaded tensors can be evaluated pointwise. - fn load_tt(path: &str, name: &str) -> SimpleTensorTrain - where - T: tensor4all_simplett::TTScalar + TensorElement + Clone, - { - let itt = tensor4all_hdf5::load_mps(path, name).unwrap(); - tensor4all_treetn::treetn_to_tensor_train::(itt.into_treetn()).unwrap() - } - - /// The `f64` bridge, checked at the value level like the `Complex64` one: - /// a fused (site dim 4) quantics TT of a Gaussian mixture is exported, - /// re-read, and evaluated against the TT it was written from. + /// The real fused-QTT cache bridge preserves values and rank. #[test] fn real_fused_qtt_round_trips_through_hdf5() { - use crate::gaussian::GaussianMixture2D; + use crate::gaussian::AnisoMixture2D; let r = 6; - let box_l = 4.0; - let mix = GaussianMixture2D::random(3, box_l, (0.5, 2.0), 7); - let (tt, _step) = - crate::gaussian::to_quantics_fused_tt(&mix, r, box_l, 1e-10, 100).unwrap(); + let box_l = 1.0; + let mix = AnisoMixture2D::random(3, 0.8, 0.1, 3.0, 7); + let tt = mix + .to_interpolative_qtt(r, box_l, 16, 1e-10, 1e-10) + .unwrap(); let path = std::env::temp_dir().join("t4a_bench_hdf5_export_roundtrip_f64.h5"); let _ = std::fs::remove_file(&path); @@ -76,7 +76,7 @@ mod tests { assert_eq!(loaded.len(), r); assert_eq!(loaded.max_bond_dim(), tt.rank()); - let back = load_tt::(path_str, "f"); + let back = load_tt_from_mps::(path_str, "f").unwrap(); for &(i, j) in &[(0u64, 0u64), (37, 20), (63, 1), (32, 32)] { let xb = crate::harness::index_to_bits(i, r); let yb = crate::harness::index_to_bits(j, r); @@ -119,7 +119,7 @@ mod tests { // analytic series at sampled grid points. let scale = (1u64 << r) as f64; for (name, series) in [("f", &f), ("g", &g)] { - let tt = load_tt::(path_str, name); + let tt = load_tt_from_mps::(path_str, name).unwrap(); for &i in &sample_grid_indices(r, 20, 11) { let got = tt.evaluate(&index_to_bits(i, r)).unwrap(); let want = series.eval(i as f64 / scale); diff --git a/src/lib.rs b/src/lib.rs index fe8401a..1558e7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ pub mod elementwise; pub mod fourier; pub mod gaussian; +pub mod gaussian_input; pub mod harness; pub mod hdf5_export; pub mod mpo_contract; diff --git a/src/mpo_contract.rs b/src/mpo_contract.rs index 6470121..022d21a 100644 --- a/src/mpo_contract.rs +++ b/src/mpo_contract.rs @@ -1,567 +1,237 @@ -//! MPO-MPO contraction wrappers (case 2) and the analytic accuracy check. -//! -//! Contraction sums over the index shared by `a`'s second site dimension and -//! `b`'s first, so with `f(x,y)` and `g(y,z)` as quantics MPOs, `contract(f, g)` -//! sums over the `y` grid and yields `h(x,z)`. +//! Global fit contraction of quantics MPOs and its sampled accuracy metric. use tensor4all_core::{DynIndex, IdxTensor, IndexLike, SvdTruncationPolicy}; use tensor4all_itensorlike::{ContractOptions, TensorTrain}; -use tensor4all_simplett::mpo::{ - contract_naive, contract_zipup, tensor4_from_data, ContractionOptions, Tensor4Ops, MPO, -}; +use tensor4all_simplett::mpo::{tensor4_from_data, Tensor4Ops, MPO}; -use crate::gaussian::{ - analytic_contraction, analytic_contraction_aniso, analytic_contraction_aniso_box, - discrete_contraction_aniso_reference, grid_coord, AnisoMixture2D, GaussianMixture2D, -}; +use crate::gaussian::{discrete_contraction_aniso_reference, grid_coord, AnisoMixture2D}; use crate::harness::{index_to_bits, sample_grid_indices}; -/// Number of full variational sweeps used by the `fit_treetn` arm. -/// -/// This is part of the benchmark definition, not an incidental value: the fit -/// cost is linear in the sweep count, so any timing comparison against the -/// naive and zipup arms is only meaningful at a fixed, stated number of -/// sweeps. One full -/// sweep (two half-sweeps) on top of the zip-up initializer is the smallest -/// setting that actually exercises the variational update. Upstream requires -/// `nhalfsweeps` to be even for the Fit method, which `with_nsweeps` ensures. +/// Full variational sweeps used by every fit contraction arm. pub const FIT_NSWEEPS: usize = 1; -/// The MPO-MPO contraction algorithms benchmarked in case 2. -/// -/// Where both engines implement an algorithm, both are benchmarked as separate -/// arms, so an engine difference is visible rather than folded into one column. -/// `simplett`'s own fit is excluded: at the pinned rev its variational update is -/// a stub upstream (see the crate docs of [`contract_fit_treetn`]). -#[derive(Clone, Copy, Debug)] -pub enum MpoAlgo { - /// Full contraction of the bond dimensions, then compression (simplett). - Naive, - /// Zip-up sweep with on-the-fly truncation, simplett engine. - ZipupSimplett, - /// Zip-up sweep with on-the-fly truncation, treetn engine via itensorlike. - ZipupTreetn, - /// Variational (DMRG-like) fit at a fixed maximum bond dimension, treetn. - FitTreetn, -} - -impl MpoAlgo { - /// Which upstream engine actually runs this arm, recorded in every record. - pub fn engine(self) -> &'static str { - match self { - MpoAlgo::Naive | MpoAlgo::ZipupSimplett => "simplett", - MpoAlgo::ZipupTreetn | MpoAlgo::FitTreetn => "treetn", - } - } -} - -/// Number of stored parameters of an MPO, the sum of its core sizes. -/// -/// The MPO counterpart of [`crate::elementwise::tt_n_params`], recorded so that -/// every case reports the size of its output in the same units. -pub fn mpo_n_params(m: &MPO) -> usize { - (0..m.len()) - .map(|i| { - let core = m.site_tensor(i); +/// Number of stored scalar entries in an MPO. +pub fn mpo_n_params(mpo: &MPO) -> usize { + (0..mpo.len()) + .map(|site| { + let core = mpo.site_tensor(site); core.left_dim() * core.site_dim_1() * core.site_dim_2() * core.right_dim() }) .sum() } -/// Contract two MPOs over their shared site index with the given algorithm. -pub fn mpo_contract( - algo: MpoAlgo, - a: &MPO, - b: &MPO, - tol: f64, - max_bond: usize, -) -> anyhow::Result> { - let opts = ContractionOptions { - tolerance: tol, - max_bond_dim: Some(max_bond), - ..ContractionOptions::default() - }; - let out = match algo { - MpoAlgo::Naive => contract_naive(a, b, Some(opts))?, - MpoAlgo::ZipupSimplett => contract_zipup(a, b, &opts)?, - MpoAlgo::ZipupTreetn => contract_zipup_treetn(a, b, tol, max_bond)?, - MpoAlgo::FitTreetn => contract_fit_treetn(a, b, tol, max_bond)?, - }; - Ok(out) -} - -/// Zip-up contraction on the treetn engine, through the same `itensorlike` -/// bridge as [`contract_fit_treetn`] and with the same max rank and SVD policy. -/// -/// Sharing the bridge with the fit arm is deliberate: the two treetn arms then -/// differ only in `ContractOptions`, so a difference between them is the -/// contraction method and not the engine or the truncation rule. -fn contract_zipup_treetn( - a: &MPO, - b: &MPO, - tol: f64, - max_bond: usize, -) -> anyhow::Result> { - let opts = ContractOptions::zipup() - .with_max_bond_dim(max_bond) - .with_svd_policy(SvdTruncationPolicy::new(tol)); - contract_via_bridge(a, b, &opts) -} - -/// Variational (DMRG-like) fit, run on the treetn engine via `itensorlike`. -/// -/// `tensor4all_simplett::mpo::contract_fit` is not used: at the pinned upstream -/// rev its local update (`update_two_site_core`) is a placeholder that returns -/// without touching the core, so it degenerates to naive plus dead sweeps. The -/// complete implementation lives in `tensor4all_treetn::treetn::fit`, reached -/// here through `tensor4all_itensorlike::TensorTrain::contract` with -/// `ContractOptions::fit()`. That is the same engine case 1 uses for its -/// elementwise fit. -fn contract_fit_treetn( - a: &MPO, - b: &MPO, - tol: f64, +/// Contract `f(x,y)` and `g(y,z)` using the TreeTN variational fit engine. +pub fn fit_mpo_contract( + left: &MPO, + right: &MPO, + rtol: f64, max_bond: usize, ) -> anyhow::Result> { - let opts = ContractOptions::fit() + let options = ContractOptions::fit() .with_max_bond_dim(max_bond) - .with_svd_policy(SvdTruncationPolicy::new(tol)) + .with_svd_policy(SvdTruncationPolicy::new(rtol)) .with_nsweeps(FIT_NSWEEPS); - contract_via_bridge(a, b, &opts) + contract_via_bridge(left, right, &options) } -/// Contract two MPOs on the treetn engine with an explicit [`ContractOptions`]. -/// -/// Splitting this out of the arm wrappers lets every treetn arm, and the tests, -/// run the exact same bridge with a different contraction method or sweep -/// count, so a comparison isolates the option that changed rather than the -/// engine. fn contract_via_bridge( - a: &MPO, - b: &MPO, - opts: &ContractOptions, + left: &MPO, + right: &MPO, + options: &ContractOptions, ) -> anyhow::Result> { - let n = a.len(); - anyhow::ensure!( - n == b.len(), - "bridge: MPO lengths differ ({n} vs {})", - b.len() - ); - - // `a` is f(x, y) and `b` is g(y, z). Sharing the y index objects between the - // two trains is what makes `contract` sum over y, exactly as the simplett - // MPO-MPO convention does. - let x_inds: Vec = (0..n).map(|i| DynIndex::new_dyn(a.site_dim(i).0)).collect(); - let y_inds: Vec = (0..n).map(|i| DynIndex::new_dyn(a.site_dim(i).1)).collect(); - let z_inds: Vec = (0..n).map(|i| DynIndex::new_dyn(b.site_dim(i).1)).collect(); - for i in 0..n { + let n = left.len(); + anyhow::ensure!(n == right.len(), "MPO lengths differ"); + let x: Vec<_> = (0..n) + .map(|site| DynIndex::new_dyn(left.site_dim(site).0)) + .collect(); + let y: Vec<_> = (0..n) + .map(|site| DynIndex::new_dyn(left.site_dim(site).1)) + .collect(); + let z: Vec<_> = (0..n) + .map(|site| DynIndex::new_dyn(right.site_dim(site).1)) + .collect(); + for site in 0..n { anyhow::ensure!( - a.site_dim(i).1 == b.site_dim(i).0, - "bridge: contracted site dims differ at site {i}" + left.site_dim(site).1 == right.site_dim(site).0, + "contracted site dimension mismatch at {site}" ); } - - let ta = mpo_to_tensortrain(a, &x_inds, &y_inds)?; - let tb = mpo_to_tensortrain(b, &y_inds, &z_inds)?; - - let tc = ta - .contract(&tb, opts) - .map_err(|e| anyhow::anyhow!("bridge: contraction failed: {e}"))?; - - tensortrain_to_mpo(&tc, &x_inds, &z_inds) + let left = mpo_to_tensortrain(left, &x, &y)?; + let right = mpo_to_tensortrain(right, &y, &z)?; + let output = left + .contract(&right, options) + .map_err(|error| anyhow::anyhow!("fit contraction failed: {error}"))?; + tensortrain_to_mpo(&output, &x, &z) } -/// Bridge an `MPO` into an `itensorlike` `TensorTrain`. -/// -/// MPO cores are `Tensor4` with shape `(left, site1, site2, right)` in -/// column-major order (upstream `mpo/types.rs`), and -/// `IdxTensor::from_dense` reads column-major data with the *first* index -/// varying fastest, so the index list is given in that same order. Boundary -/// links are dimension 1 in every `MPO` (checked by `MPO::new`), so they are -/// dropped rather than carried as dummy indices: `TensorTrain::new` requires -/// adjacent sites to share exactly one index and identifies links purely by -/// shared index id, and a leading or trailing extent-1 axis does not change -/// the column-major layout. +/// Bridge an MPO into an indexed tensor train using the supplied physical indices. pub fn mpo_to_tensortrain( - m: &MPO, - site1: &[DynIndex], - site2: &[DynIndex], + mpo: &MPO, + first: &[DynIndex], + second: &[DynIndex], ) -> anyhow::Result { - let n = m.len(); - let links: Vec = (0..n.saturating_sub(1)) - .map(|i| DynIndex::new_dyn(m.link_dim(i))) + let n = mpo.len(); + anyhow::ensure!( + first.len() == n && second.len() == n, + "site-index count mismatch" + ); + let links: Vec<_> = (0..n.saturating_sub(1)) + .map(|site| DynIndex::new_dyn(mpo.link_dim(site))) .collect(); - let mut tensors = Vec::with_capacity(n); - for i in 0..n { - let core = m.site_tensor(i); + for site in 0..n { + let core = mpo.site_tensor(site); anyhow::ensure!( - i > 0 || core.left_dim() == 1, - "bridge: leading MPO bond is not 1" + site > 0 || core.left_dim() == 1, + "leading MPO bond is not 1" ); anyhow::ensure!( - i + 1 < n || core.right_dim() == 1, - "bridge: trailing MPO bond is not 1" + site + 1 < n || core.right_dim() == 1, + "trailing MPO bond is not 1" ); let mut indices = Vec::with_capacity(4); - if i > 0 { - indices.push(links[i - 1].clone()); + if site > 0 { + indices.push(links[site - 1].clone()); } - indices.push(site1[i].clone()); - indices.push(site2[i].clone()); - if i + 1 < n { - indices.push(links[i].clone()); + indices.push(first[site].clone()); + indices.push(second[site].clone()); + if site + 1 < n { + indices.push(links[site].clone()); } tensors.push(IdxTensor::from_dense(indices, core.to_col_major_vec())?); } - - TensorTrain::new(tensors).map_err(|e| anyhow::anyhow!("bridge: TensorTrain::new failed: {e}")) + TensorTrain::new(tensors).map_err(|error| anyhow::anyhow!("invalid bridged MPO: {error}")) } -/// Bridge an `itensorlike` `TensorTrain` back to an `MPO`. -/// -/// The contraction preserves the external site index objects, so each result -/// core is permuted into `(left, site1, site2, right)` and read out as -/// column-major data, which is what `tensor4_from_data` expects. +/// Convert an indexed tensor train back to an MPO in the requested physical order. pub fn tensortrain_to_mpo( tt: &TensorTrain, - site1: &[DynIndex], - site2: &[DynIndex], + first: &[DynIndex], + second: &[DynIndex], ) -> anyhow::Result> { - let n = tt.len(); - let mut cores = Vec::with_capacity(n); - for i in 0..n { - let tensor = tt - .tensor(i) - .map_err(|e| anyhow::anyhow!("bridge: missing result tensor at site {i}: {e}"))?; - let left = if i > 0 { tt.linkind(i - 1) } else { None }; - let right = if i + 1 < n { tt.linkind(i) } else { None }; + let mut cores = Vec::with_capacity(tt.len()); + for site in 0..tt.len() { + let tensor = tt.tensor(site)?; + let left = (site > 0).then(|| tt.linkind(site - 1)).flatten(); + let right = (site + 1 < tt.len()).then(|| tt.linkind(site)).flatten(); let mut order = Vec::with_capacity(4); order.extend(left.clone()); - order.push(site1[i].clone()); - order.push(site2[i].clone()); + order.push(first[site].clone()); + order.push(second[site].clone()); order.extend(right.clone()); anyhow::ensure!( order.len() == tensor.indices().len(), - "bridge: result core at site {i} has {} indices, expected {}", - tensor.indices().len(), - order.len() + "result core index-count mismatch at {site}" ); - let data = tensor.permute_indices(&order)?.to_vec::()?; - let ldim = left.map_or(1, |ix| ix.dim()); - let rdim = right.map_or(1, |ix| ix.dim()); cores.push(tensor4_from_data( - data, - ldim, - site1[i].dim(), - site2[i].dim(), - rdim, + tensor.permute_indices(&order)?.to_vec::()?, + left.map_or(1, |index| index.dim()), + first[site].dim(), + second[site].dim(), + right.map_or(1, |index| index.dim()), )?); } Ok(MPO::new(cores)?) } -/// Relative max error of `h` vs the analytic y-integral, normalized by the max -/// sampled `|analytic|` value. The MPO holds the plain sum over the y grid, so -/// multiply by `dy` to approximate the integral. -#[allow(clippy::too_many_arguments)] -pub fn max_rel_error_vs_analytic( - h: &MPO, - dy: f64, - f: &GaussianMixture2D, - g: &GaussianMixture2D, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> f64 { - max_rel_error_vs_reference(h, dy, r, box_l, n_samples, seed, |x, z| { - analytic_contraction(f, g, x, z) - }) -} - -/// Relative sampled error against the anisotropic closed-form contraction. -#[allow(clippy::too_many_arguments)] -pub fn max_rel_error_vs_aniso_analytic( - h: &MPO, - dy: f64, - f: &AnisoMixture2D, - g: &AnisoMixture2D, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> f64 { - max_rel_error_vs_reference(h, dy, r, box_l, n_samples, seed, |x, z| { - analytic_contraction_aniso(f, g, x, z) - }) -} - -/// Relative sampled error against the finite-box anisotropic contraction. -#[allow(clippy::too_many_arguments)] -pub fn max_rel_error_vs_aniso_box( - h: &MPO, - dy: f64, - f: &AnisoMixture2D, - g: &AnisoMixture2D, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, -) -> f64 { - max_rel_error_vs_reference(h, dy, r, box_l, n_samples, seed, |x, z| { - analytic_contraction_aniso_box(f, g, x, z, box_l) - }) -} - -/// Relative sampled error against the quantics grid-sum reference. +/// Deterministic sampled relative-L2 error against the finite quantics grid sum. #[allow(clippy::too_many_arguments)] -pub fn max_rel_error_vs_aniso_grid( - h: &MPO, - dy: f64, - f: &AnisoMixture2D, - g: &AnisoMixture2D, +pub fn sampled_relative_l2_vs_aniso_grid( + output: &MPO, + grid_step: f64, + left: &AnisoMixture2D, + right: &AnisoMixture2D, r: usize, box_l: f64, - n_samples: usize, + samples: usize, seed: u64, -) -> f64 { - max_rel_error_vs_reference(h, dy, r, box_l, n_samples, seed, |x, z| { - discrete_contraction_aniso_reference(f, g, x, z, r, box_l) - }) -} - -fn max_rel_error_vs_reference( - h: &MPO, - dy: f64, - r: usize, - box_l: f64, - n_samples: usize, - seed: u64, - reference: impl Fn(f64, f64) -> f64, -) -> f64 { - let xs = sample_grid_indices(r, n_samples, seed); - let zs = sample_grid_indices(r, n_samples, seed.wrapping_add(1)); - let mut max_abs = 0.0f64; - let mut max_ref = 0.0f64; +) -> anyhow::Result { + let xs = sample_grid_indices(r, samples, seed); + let zs = sample_grid_indices(r, samples, seed.wrapping_add(1)); + let mut squared_error = 0.0; + let mut squared_reference = 0.0; for (&ix, &iz) in xs.iter().zip(&zs) { - let x = grid_coord(ix, r, box_l); - let z = grid_coord(iz, r, box_l); - let xb = index_to_bits(ix, r); - let zb = index_to_bits(iz, r); - let mut idx = Vec::with_capacity(2 * r); - for n in 0..r { - idx.push(xb[n]); - idx.push(zb[n]); - } - let got = h.evaluate(&idx).unwrap() * dy; - let want = reference(x, z); - max_abs = max_abs.max((got - want).abs()); - max_ref = max_ref.max(want.abs()); + let bits: Vec<_> = index_to_bits(ix, r) + .into_iter() + .zip(index_to_bits(iz, r)) + .flat_map(|(x, z)| [x, z]) + .collect(); + let expected = discrete_contraction_aniso_reference( + left, + right, + grid_coord(ix, r, box_l), + grid_coord(iz, r, box_l), + r, + box_l, + ); + let error = output.evaluate(&bits)? * grid_step - expected; + squared_error += error * error; + squared_reference += expected * expected; } - max_abs / max_ref.max(f64::MIN_POSITIVE) + anyhow::ensure!(squared_reference > 0.0, "zero contraction reference norm"); + Ok((squared_error / squared_reference).sqrt()) } -/// Maximum absolute difference between two MPOs at sampled `(x, z)` grid points. -pub fn max_sampled_mpo_diff( - left: &MPO, - right: &MPO, - r: usize, - n_samples: usize, - seed: u64, -) -> f64 { - sampled_mpo_diff_and_scale(left, right, r, n_samples, seed).0 -} - -/// Sampled maximum difference divided by the largest sampled magnitude. +/// Sampled maximum relative difference between two MPOs. pub fn max_sampled_mpo_relative_diff( left: &MPO, right: &MPO, r: usize, - n_samples: usize, - seed: u64, -) -> f64 { - let (difference, scale) = sampled_mpo_diff_and_scale(left, right, r, n_samples, seed); - difference / scale.max(f64::MIN_POSITIVE) -} - -fn sampled_mpo_diff_and_scale( - left: &MPO, - right: &MPO, - r: usize, - n_samples: usize, + samples: usize, seed: u64, -) -> (f64, f64) { - let xs = sample_grid_indices(r, n_samples, seed); - let zs = sample_grid_indices(r, n_samples, seed.wrapping_add(1)); - xs.iter() - .zip(&zs) - .fold((0.0_f64, 0.0_f64), |(difference, scale), (&ix, &iz)| { - let xb = index_to_bits(ix, r); - let zb = index_to_bits(iz, r); - let indices = (0..r) - .flat_map(|site| [xb[site], zb[site]]) - .collect::>(); - let left_value = left.evaluate(&indices).unwrap(); - let right_value = right.evaluate(&indices).unwrap(); - ( - difference.max((left_value - right_value).abs()), - scale.max(left_value.abs()).max(right_value.abs()), - ) - }) +) -> anyhow::Result { + let xs = sample_grid_indices(r, samples, seed); + let zs = sample_grid_indices(r, samples, seed.wrapping_add(1)); + let mut difference = 0.0_f64; + let mut scale = 0.0_f64; + for (&ix, &iz) in xs.iter().zip(&zs) { + let bits: Vec<_> = index_to_bits(ix, r) + .into_iter() + .zip(index_to_bits(iz, r)) + .flat_map(|(x, z)| [x, z]) + .collect(); + let a = left.evaluate(&bits)?; + let b = right.evaluate(&bits)?; + difference = difference.max((a - b).abs()); + scale = scale.max(a.abs()).max(b.abs()); + } + Ok(difference / scale.max(f64::MIN_POSITIVE)) } #[cfg(test)] mod tests { use super::*; - use crate::gaussian::{to_quantics_mpo, GaussianMixture2D}; - - /// Evaluate `h` at `n` pseudo-random `(x, z)` grid points. - fn sample_values(h: &MPO, r: usize, n: usize, seed: u64) -> Vec { - let xs = sample_grid_indices(r, n, seed); - let zs = sample_grid_indices(r, n, seed.wrapping_add(1)); - xs.iter() - .zip(&zs) - .map(|(&ix, &iz)| { - let xb = index_to_bits(ix, r); - let zb = index_to_bits(iz, r); - let mut idx = Vec::with_capacity(2 * r); - for k in 0..r { - idx.push(xb[k]); - idx.push(zb[k]); - } - h.evaluate(&idx).unwrap() - }) - .collect() - } - - #[test] - fn all_algorithms_agree_with_analytic_integral() { - let (r, l) = (8, 6.0); - let f = GaussianMixture2D::random(3, l, (0.5, 2.0), 20); - let g = GaussianMixture2D::random(3, l, (0.5, 2.0), 21); - let (fa, dy) = to_quantics_mpo(&f, r, l, 1e-6, 128).unwrap(); - let (gb, _) = to_quantics_mpo(&g, r, l, 1e-6, 128).unwrap(); - for algo in [ - MpoAlgo::Naive, - MpoAlgo::ZipupSimplett, - MpoAlgo::ZipupTreetn, - MpoAlgo::FitTreetn, - ] { - let h = mpo_contract(algo, &fa, &gb, 1e-6, 128).unwrap(); - let err = max_rel_error_vs_analytic(&h, dy, &f, &g, r, l, 50, 22); - // R=8 discretization floor dominates; bound is loose on purpose - // (measured 1.7e-6 for naive and fit, 2.8e-6 for the two zipup - // arms, at the pinned rev). - assert!(err < 1e-2, "{algo:?}: rel err {err}"); - } - } - - /// Max absolute difference between two MPOs at the same sampled points. - fn max_sampled_diff(p: &MPO, q: &MPO, r: usize, n: usize, seed: u64) -> f64 { - let vp = sample_values(p, r, n, seed); - let vq = sample_values(q, r, n, seed); - vp.iter() - .zip(&vq) - .map(|(a, b)| (a - b).abs()) - .fold(0.0f64, f64::max) - } + use crate::gaussian::fused_qtt_to_mpo; - /// Guard that `MpoAlgo::FitTreetn` reaches the variational engine rather - /// than silently returning a zip-up result. - /// - /// Untruncated, fit and zipup converge to the same tensor, so the arms are - /// separated under a bond dimension small enough to force real truncation - /// error. The load-bearing comparison is against the `ZipupTreetn` arm: - /// same engine, same bridge, same truncation policy, same max rank, so the - /// only difference is the contraction method and a difference in the output - /// can only come from the variational updates. (Comparing against simplett - /// zipup would not prove that, since it differs in engine and truncation - /// rule as well and would separate even if the variational sweep were a - /// no-op.) The simplett arm is kept as a weaker secondary check that - /// `FitTreetn` does not dispatch there. - /// - /// Measured at `max_bond = 8` with the pinned rev: fit vs treetn zipup - /// 1.18, fit vs simplett zipup 1.18, on a sampled scale of 13.2 (about 9%), - /// while the two zipup results agree to 2.0e-14. So the two zipup paths - /// coincide and the variational sweep is what moves the answer. #[test] - fn fit_differs_from_zipup_under_forced_truncation() { - let (r, l, max_bond) = (8, 6.0, 8); - let f = GaussianMixture2D::random(3, l, (0.5, 2.0), 20); - let g = GaussianMixture2D::random(3, l, (0.5, 2.0), 21); - let (fa, _dy) = to_quantics_mpo(&f, r, l, 1e-6, 128).unwrap(); - let (gb, _) = to_quantics_mpo(&g, r, l, 1e-6, 128).unwrap(); - - let h_fit = mpo_contract(MpoAlgo::FitTreetn, &fa, &gb, 1e-6, max_bond).unwrap(); - - // Same engine, same bridge, same truncation policy, same max rank. - let h_treetn_zip = mpo_contract(MpoAlgo::ZipupTreetn, &fa, &gb, 1e-6, max_bond).unwrap(); - let diff_same_engine = max_sampled_diff(&h_fit, &h_treetn_zip, r, 20, 33); - assert!( - diff_same_engine > 1e-14, - "fit output matches treetn zipup at max_bond={max_bond}: the variational \ - sweeps are not changing the zip-up initializer (max diff {diff_same_engine:e})" - ); - - // Weaker: FitTreetn is not silently dispatching to simplett zipup. - let h_simplett_zip = - mpo_contract(MpoAlgo::ZipupSimplett, &fa, &gb, 1e-6, max_bond).unwrap(); - let diff_cross_engine = max_sampled_diff(&h_fit, &h_simplett_zip, r, 20, 33); - assert!( - diff_cross_engine > 1e-14, - "fit output is bit-identical to simplett zipup at max_bond={max_bond} \ - (max diff {diff_cross_engine:e})" - ); - } - - /// The two zipup arms are different engines but should agree closely when - /// the rank cap does not bind, which also pins that `ZipupTreetn` really - /// computes the contraction rather than something structurally different. - #[test] - fn zipup_arms_agree_when_untruncated() { - let (r, l) = (8, 6.0); - let f = GaussianMixture2D::random(3, l, (0.5, 2.0), 20); - let g = GaussianMixture2D::random(3, l, (0.5, 2.0), 21); - let (fa, _dy) = to_quantics_mpo(&f, r, l, 1e-6, 128).unwrap(); - let (gb, _) = to_quantics_mpo(&g, r, l, 1e-6, 128).unwrap(); - - let h_s = mpo_contract(MpoAlgo::ZipupSimplett, &fa, &gb, 1e-10, 256).unwrap(); - let h_t = mpo_contract(MpoAlgo::ZipupTreetn, &fa, &gb, 1e-10, 256).unwrap(); - let scale = sample_values(&h_s, r, 20, 33) - .into_iter() - .fold(0.0f64, |m, v| m.max(v.abs())); - let diff = max_sampled_diff(&h_s, &h_t, r, 20, 33); - assert!( - diff < 1e-6 * scale.max(1.0), - "zipup arms disagree: max diff {diff:e} on scale {scale:e}" - ); - } - - #[test] - fn partitioned_tt_and_chain_treetn_match_each_other() { - use crate::patched_mpo::PatchedMpoPair; - - let (r, l, patch_cap) = (6, 6.0, 36); - let f = GaussianMixture2D::random(3, l, (0.5, 2.0), 40); - let g = GaussianMixture2D::random(3, l, (0.5, 2.0), 41); - let (left, _dy) = to_quantics_mpo(&f, r, l, 1e-8, 128).unwrap(); - let (right, _) = to_quantics_mpo(&g, r, l, 1e-8, 128).unwrap(); - let patched = PatchedMpoPair::new(&left, &right, 1e-8, patch_cap).unwrap(); - let input_chi = patched.input_max_bond(); - assert!(input_chi > patch_cap); - assert!(patched.input_patch_counts().0 > 1); - - let tt = patched.contract_fit_tt(1e-10, input_chi).unwrap(); - let tree = patched.contract_fit_treetn(1e-10, input_chi).unwrap(); - let cross_diff = max_sampled_mpo_diff(&tt.mpo, &tree.mpo, r, 64, 42); - - assert_eq!(tt.n_patches, tree.n_patches); - assert_eq!(tt.max_patch_bond, tree.max_patch_bond); - assert!(tt.max_patch_bond <= input_chi); - assert!( - cross_diff < 1e-8, - "partitioned outputs differ by {cross_diff:e}" - ); + fn fit_contraction_matches_the_grid_reference() { + let (r, box_l) = (6, 1.0); + let left_mix = AnisoMixture2D::random(2, 0.8, 0.15, 2.0, 1); + let right_mix = AnisoMixture2D::random(2, 0.8, 0.15, 2.0, 2); + let left = fused_qtt_to_mpo( + &left_mix + .to_interpolative_qtt(r, box_l, 12, 1e-9, 1e-10) + .unwrap(), + ) + .unwrap(); + let right = fused_qtt_to_mpo( + &right_mix + .to_interpolative_qtt(r, box_l, 12, 1e-9, 1e-10) + .unwrap(), + ) + .unwrap(); + let output = fit_mpo_contract(&left, &right, 1e-8, 128).unwrap(); + let error = sampled_relative_l2_vs_aniso_grid( + &output, + 2.0 * box_l / (1usize << r) as f64, + &left_mix, + &right_mix, + r, + box_l, + 64, + 7, + ) + .unwrap(); + assert!(error < 1e-5, "relative L2 error={error:.3e}"); } } diff --git a/src/patched.rs b/src/patched.rs index 987ae23..9aef512 100644 --- a/src/patched.rs +++ b/src/patched.rs @@ -11,24 +11,6 @@ //! honoured everywhere and the price of a hard region is paid in patch count //! rather than in global rank. //! -//! There are two constructions of that patched input here, and they differ only -//! in what decides a split. -//! -//! * [`patched_input_from_global`], the default of case 5, builds one global -//! train first and hands it to `partitionedtt::add_with_patching`, which -//! truncates each subdomain against its volume share of the global squared -//! budget and splits whatever still sits above the rank cap. The split index is -//! chosen by a [`PatchSplitStrategy`], and no TCI runs inside the loop: the -//! whole decision is made from Frobenius norms of an already-built train. -//! * [`patched_input`] instead runs `partitionedtt::adaptiveinterpolate`, which -//! never forms a global train at all: it runs a TCI2 per patch on the function -//! itself and splits a patch whose own TCI does not converge under the cap. -//! That is the construction the case is eventually written for, since it is the -//! one whose cost never passes through a global rank. It used to trip a TCI2 -//! defect on a patch of some instances, fixed upstream and included at the -//! pinned revision (README known issue 11); it is not the default because for -//! the same cap it splits far harder and returns a much larger representation. -//! //! The product is then formed patch pair by patch pair. Two patches contribute //! only if their projectors are compatible, in which case the product lives on //! the intersection of the two subdomains. Both partitions cover the domain @@ -41,8 +23,8 @@ //! //! 1. The per-patch product runs on the FREE sites only. The sites fixed by the //! merged projector are sliced out of both inputs first (which is exactly the -//! projection, since a projected site of an `adaptiveinterpolate` patch train -//! carries a one-hot core), the product is formed over the remaining sites, +//! projection, since a projected site carries a one-hot core), the product is +//! formed over the remaining sites, //! and the fixed sites are put back afterwards as one-hot cores. This keeps //! the work proportional to the patch volume instead of the box volume, and //! it is what makes the `aci` engine usable at all: on the embedded train the @@ -64,9 +46,8 @@ use tensor4all_core::{DynIndex, IdxTensor}; use tensor4all_partitionedtt::{ - adaptiveinterpolate, add_with_patching, truncate_adaptive, AdaptiveInterpolateOptions, - MultiIndex, PartitionedTT, PatchSplitStrategy, PatchingOptions, Projector, SubDomainTT, - TCI2Options, TensorTrain as ItTensorTrain, + add_with_patching, truncate_adaptive, PartitionedTT, PatchSplitStrategy, PatchingOptions, + Projector, SubDomainTT, TensorTrain as ItTensorTrain, }; use tensor4all_simplett::{ tensor3_from_data, AbstractTensorTrain, SimpleTensorTrain as SimpleTT, Tensor3Ops, @@ -78,15 +59,10 @@ use crate::harness::{index_to_bits, sample_grid_indices}; /// Which engine forms the product inside one patch pair. /// -/// The four variants are the four global arms of case 3, run on the projected -/// patch trains instead of on the global trains, so a difference between a -/// patched arm and its global namesake is the patching and not the engine. +/// The two variants match the global fit and ACI arms of case 2, but run on +/// projected patch trains. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum PatchedEngine { - /// Local bond-Kronecker product plus an SVD sweep, written in this crate. - Naive, - /// `tensor4all_treetn::hadamard` with the one-pass zip-up contraction. - ZipupTreetn, /// `tensor4all_treetn::hadamard` with the variational fit contraction. FitTreetn, /// `tensor4all_aci::elementwise` cross interpolation of the product. @@ -94,45 +70,16 @@ pub enum PatchedEngine { } impl PatchedEngine { - /// Arm name as it appears in the records. - pub fn arm_name(self) -> &'static str { - match self { - PatchedEngine::Naive => "patched_naive", - PatchedEngine::ZipupTreetn => "patched_zipup_treetn", - PatchedEngine::FitTreetn => "patched_fit_treetn", - PatchedEngine::Aci => "patched_aci", - } - } - - /// Upstream engine that actually runs the per-patch product. - pub fn engine(self) -> &'static str { - self.algo().engine() - } - fn algo(self) -> ElementwiseAlgo { match self { - PatchedEngine::Naive => ElementwiseAlgo::Naive, - PatchedEngine::ZipupTreetn => ElementwiseAlgo::Zipup, PatchedEngine::FitTreetn => ElementwiseAlgo::Fit, PatchedEngine::Aci => ElementwiseAlgo::Aci, } } } -/// Parse an arm name back into an engine, for `BENCH_ALGOS`. -pub fn parse_patched_engine(name: &str) -> Option { - [ - PatchedEngine::Naive, - PatchedEngine::ZipupTreetn, - PatchedEngine::FitTreetn, - PatchedEngine::Aci, - ] - .into_iter() - .find(|engine| engine.arm_name() == name) -} - /// One fused quantics site index per bit, dimension 4, in the layout -/// `gaussian::to_quantics_fused_tt` produces: local index `x_bit + 2 * y_bit`, +/// the interpolative Gaussian QTT uses: local index `x_bit + 2 * y_bit`, /// most significant bit first. /// /// The two inputs of a product MUST be built over the same vector: projector @@ -142,144 +89,6 @@ pub fn fused_site_indices(r: usize) -> Vec { (0..r).map(|_| DynIndex::new_dyn(4)).collect() } -/// Grid coordinates of one fused quantics multi-index. -/// -/// Site `n` carries `x_bit + 2 * y_bit` of bit position `n` counted from the -/// most significant, which is the layout of `fused_site_indices`. -fn fused_to_coords(index: &MultiIndex, r: usize, box_l: f64) -> (f64, f64) { - let mut ix = 0u64; - let mut iy = 0u64; - for (n, &fused) in index.iter().enumerate() { - let shift = r - 1 - n; - ix |= ((fused & 1) as u64) << shift; - iy |= (((fused >> 1) & 1) as u64) << shift; - } - (grid_coord(ix, r, box_l), grid_coord(iy, r, box_l)) -} - -/// Options for the patched construction of one input. -#[derive(Clone, Copy, Debug)] -pub struct PatchedInputOptions { - /// Absolute TCI tolerance for every patch. - /// - /// Absolute, not relative: `TCI2Options::normalize_error` is switched off so - /// that a patch sitting in a near-empty region of the box converges at rank - /// one instead of being asked for eight relative digits of a quantity that - /// contributes nothing. The caller sets this to `rtol` times the sampled - /// scale of the function, so the accuracy is uniform across the box. - pub abs_tol: f64, - /// Per-patch rank cap. A patch whose TCI run does not converge below this - /// cap is split at the next site, which is the stopping rule: split until - /// the bond dimension fits under the cap. - pub max_bond_dim: usize, - /// Half-sweep limit of each patch's TCI run. - /// - /// Exposed because a run that stops at its iteration limit is not converged, - /// so its patch is split whatever its rank was, which would make the patch - /// tree a measurement of the iteration limit. Measured at the pinned revision - /// on the case-5 instance at `N` = 8, that is not what happens: raising this - /// from the upstream 20 to 200 left the patch counts and the patch ranks - /// unchanged and cost six times the build time, so the splitting there is - /// driven by the tolerance and the rank cap, and 20 is the right default. - pub max_iter: usize, - /// Seed of the deterministic initial-pivot search. - pub seed: u64, -} - -/// Build the patched representation of a 2D Gaussian mixture on `[-L, L)^2`. -/// -/// The patch order is the site order, most significant digit first, so the first -/// split fixes a quadrant of the box, the second a sub-quadrant, and so on: -/// coarse to fine, which is what makes a patch a contiguous region of the box. -pub fn patched_input( - mix: &M, - sites: &[DynIndex], - box_l: f64, - options: PatchedInputOptions, -) -> anyhow::Result { - let r = sites.len(); - let mixture = mix.clone(); - let evaluate = move |index: &MultiIndex| -> f64 { - let (x, y) = fused_to_coords(index, r, box_l); - mixture.eval(x, y) - }; - let tci_options = TCI2Options { - tolerance: options.abs_tol, - max_bond_dim: Some(options.max_bond_dim), - max_iter: options.max_iter, - normalize_error: false, - seed: Some(options.seed), - ..TCI2Options::default() - }; - let opts = AdaptiveInterpolateOptions { - tci_options, - patch_order: sites.to_vec(), - ..AdaptiveInterpolateOptions::default() - }; - adaptiveinterpolate:: Vec>( - evaluate, - None, - sites.to_vec(), - Vec::new(), - opts, - ) - .map_err(|e| anyhow::anyhow!("adaptiveinterpolate failed: {e}")) -} - -/// Which construction turns a function into a patched input. -/// -/// Recorded in every case-5 record as `input_path`, because the two are not the -/// same measurement: one of them pays for a global train before it splits and the -/// other never builds one. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum PatchedInputPath { - /// Frobenius-norm-driven splitting of a global train, - /// [`patched_input_from_global`]. - NormDriven, - /// TCI2-driven splitting of the function itself, [`patched_input`]. - TciDriven, -} - -impl PatchedInputPath { - /// Name as it appears in `BENCH_PATCH_INPUT` and in the records. - pub fn label(self) -> &'static str { - match self { - PatchedInputPath::NormDriven => "norm", - PatchedInputPath::TciDriven => "tci", - } - } -} - -/// Parse `BENCH_PATCH_INPUT`. -pub fn parse_input_path(name: &str) -> Option { - [PatchedInputPath::NormDriven, PatchedInputPath::TciDriven] - .into_iter() - .find(|path| path.label() == name) -} - -/// Parse `BENCH_PATCH_SPLIT` into an upstream split strategy. -/// -/// `gain` is `ExactParameterGain`, the upstream default, which forms and -/// budget-truncates the children of every candidate index and keeps the cheapest. -/// `sequential` takes the first unprojected index of the patch order instead, so -/// the splitting runs strictly coarse to fine. -pub fn parse_split_strategy(name: &str) -> Option { - match name { - "gain" => Some(PatchSplitStrategy::ExactParameterGain), - "sequential" => Some(PatchSplitStrategy::Sequential), - _ => None, - } -} - -/// Name of a split strategy as it appears in `BENCH_PATCH_SPLIT` and in the -/// records. -pub fn split_strategy_label(strategy: PatchSplitStrategy) -> &'static str { - match strategy { - PatchSplitStrategy::ExactParameterGain => "gain", - PatchSplitStrategy::Sequential => "sequential", - } -} - /// Options for the norm-driven patched construction of one input. #[derive(Clone, Copy, Debug)] pub struct NormPatchedInputOptions { @@ -289,8 +98,7 @@ pub struct NormPatchedInputOptions { /// patch volume, both while the splitting decides whether a patch is over its /// cap and in the final truncation. Relative to the norm of the whole /// function, so a patch in a near-empty corner of the box is not asked for - /// digits of a quantity that contributes nothing, which is what the TCI-driven - /// path needs its absolute tolerance for. + /// digits of a quantity that contributes nothing. pub rtol: f64, /// Per-patch rank cap. A subdomain whose budget-truncated bond dimension is /// still above this is split, which is the stopping rule. @@ -392,13 +200,8 @@ pub struct PatchedProductOptions { /// budgeting happens once at the end in [`truncate_adaptive`]. For the three /// SVD-based engines this is a singular value threshold relative to the /// largest singular value of the patch; the `aci` engine runs - /// [`AciTolerance::Absolute`], which is the same rule as the per-patch input - /// TCI tolerance and for the same reason: a patch in a near-empty corner of - /// the box must not be held to a tolerance relative to its own magnitude, - /// since its share of the global error budget is what matters. Measured on - /// the smooth family at `N` = 32, the upstream scale-relative criterion left - /// the `patched_aci` arm at `5.3e-4` while the three other engines returned - /// `3.5e-8`; on an absolute budget all four agree again. + /// [`AciTolerance::Absolute`] because a patch in a near-empty region must not + /// be held to a tolerance relative to its own magnitude. pub product_tol: f64, /// Rank cap for the per-patch product, before the final budgeting. pub product_max_bond_dim: usize, @@ -431,13 +234,8 @@ pub fn patched_elementwise( /// The two halves of the product are a loop over compatible patch pairs and one /// final [`truncate_adaptive`], and they scale differently: the pair loop grows /// with the patch count and with the cube of the patch rank, while the final -/// budgeting has to gauge and truncate every collected patch once. Which half -/// dominates moves with the family and with the engine: measured on the smooth -/// family at `N` = 64, the budgeting was 23.1 s of the 40.1 s of `patched_aci` -/// against 4.7 s of the 36.0 s of `patched_fit_treetn`, while on the aniso family -/// at `N` = 512 the pair loop dominates both. So a case-5 total is not -/// interpretable without this split, and the runner records it in every patched -/// record. +/// budgeting has to gauge and truncate every collected patch once. The runner +/// records both parts because either can dominate. #[derive(Clone, Copy, Debug, Default)] pub struct PatchedProductStats { /// Compatible patch pairs contracted, which is the number of output patches @@ -868,12 +666,7 @@ pub fn max_patch_bond(partitioned: &PartitionedTT) -> usize { .unwrap_or(0) } -/// Case-5 error metric: sampled max relative error of a patched product against -/// the exact pointwise product of the two mixtures. -/// -/// Same sampling, same normalization and same `error_metric` name as -/// [`crate::elementwise::max_rel_error_vs_mixture_product`], so a case-5 number -/// is directly comparable with a case-4 one. +/// Sampled maximum relative error of a patched product against the exact product. #[allow(clippy::too_many_arguments)] pub fn max_rel_error_patched( h: &PartitionedTT, @@ -903,468 +696,151 @@ pub fn max_rel_error_patched( Ok(max_abs / max_ref.max(f64::MIN_POSITIVE)) } +/// Deterministic sampled relative-L2 error of a patched product. +#[allow(clippy::too_many_arguments)] +pub fn sampled_relative_l2_patched( + output: &PartitionedTT, + sites: &[DynIndex], + left: &A, + right: &B, + box_l: f64, + samples: usize, + seed: u64, +) -> anyhow::Result { + let r = sites.len(); + let xs = sample_grid_indices(r, samples, seed); + let ys = sample_grid_indices(r, samples, seed.wrapping_add(1)); + let mut squared_error = 0.0; + let mut squared_reference = 0.0; + for (&ix, &iy) in xs.iter().zip(&ys) { + let x = grid_coord(ix, r, box_l); + let y = grid_coord(iy, r, box_l); + let fused: Vec<_> = index_to_bits(ix, r) + .into_iter() + .zip(index_to_bits(iy, r)) + .map(|(x, y)| x + 2 * y) + .collect(); + let expected = left.eval(x, y) * right.eval(x, y); + let error = eval_patched(output, sites, &fused)? - expected; + squared_error += error * error; + squared_reference += expected * expected; + } + anyhow::ensure!(squared_reference > 0.0, "zero elementwise reference norm"); + Ok((squared_error / squared_reference).sqrt()) +} + #[cfg(test)] mod tests { use super::*; - use crate::elementwise::mixture_product_scales; - use crate::gaussian::GaussianMixture2D; - - /// Two small mixtures at R = 6 and a per-patch cap tight enough that the - /// construction really splits, so the test exercises the patch machinery - /// rather than a one-patch degenerate case. - fn setup( - r: usize, - chi_p: usize, - ) -> ( - Vec, - GaussianMixture2D, - GaussianMixture2D, - PartitionedTT, - PartitionedTT, - f64, - f64, - ) { - let box_l = 4.0; - let f = GaussianMixture2D::random(3, box_l, (0.5, 8.0), 1); - let g = GaussianMixture2D::random(3, box_l, (0.5, 8.0), 2); - let sites = fused_site_indices(r); - let scales = mixture_product_scales(&f, &g, r, box_l, 128, 99); - let rtol = 1e-8; - let fp = patched_input( - &f, - &sites, - box_l, - PatchedInputOptions { - abs_tol: rtol * scales.input_scale_f, - max_bond_dim: chi_p, - max_iter: 200, - seed: 1, - }, - ) - .unwrap(); - let gp = patched_input( - &g, - &sites, - box_l, - PatchedInputOptions { - abs_tol: rtol * scales.input_scale_g, - max_bond_dim: chi_p, - max_iter: 200, - seed: 2, - }, - ) - .unwrap(); - (sites, f, g, fp, gp, box_l, rtol) - } + use crate::elementwise::{max_rel_error_vs_product, AciTolerance}; + use crate::gaussian::AnisoMixture2D; - /// The same two mixtures through the norm-driven path: one global train per - /// input at the same tolerance, bridged and split by `add_with_patching`. - #[allow(clippy::type_complexity)] - fn setup_norm( - r: usize, - chi_p: usize, - ) -> ( + fn fixture() -> ( Vec, - GaussianMixture2D, - GaussianMixture2D, + AnisoMixture2D, + AnisoMixture2D, + SimpleTT, + SimpleTT, PartitionedTT, PartitionedTT, - f64, - f64, ) { - use crate::gaussian::to_quantics_fused_tt; - - let box_l = 4.0; - let f = GaussianMixture2D::random(3, box_l, (0.5, 8.0), 1); - let g = GaussianMixture2D::random(3, box_l, (0.5, 8.0), 2); + let (r, box_l) = (6, 1.0); + let left_mix = AnisoMixture2D::random(2, 0.8, 0.15, 2.0, 1); + let right_mix = AnisoMixture2D::random(2, 0.8, 0.15, 2.0, 2); + let left = left_mix + .to_interpolative_qtt(r, box_l, 12, 1e-9, 1e-10) + .unwrap(); + let right = right_mix + .to_interpolative_qtt(r, box_l, 12, 1e-9, 1e-10) + .unwrap(); let sites = fused_site_indices(r); - let rtol = 1e-8; let options = NormPatchedInputOptions { - rtol, - max_bond_dim: chi_p, - strategy: PatchSplitStrategy::default(), + rtol: 1e-8, + max_bond_dim: crate::gaussian_input::PATCH_CAP, + strategy: PatchSplitStrategy::Sequential, }; - let (fa, _) = to_quantics_fused_tt(&f, r, box_l, rtol, 256).unwrap(); - let (gb, _) = to_quantics_fused_tt(&g, r, box_l, rtol, 256).unwrap(); - let fp = patched_input_from_global(&fa, &sites, options).unwrap(); - let gp = patched_input_from_global(&gb, &sites, options).unwrap(); - (sites, f, g, fp, gp, box_l, rtol) - } - - fn product_options(engine: PatchedEngine, rtol: f64) -> PatchedProductOptions { - PatchedProductOptions { - engine, - product_tol: rtol * 1e-2, - product_max_bond_dim: 256, - rtol, - max_bond_dim: 256, - } + let patched_left = patched_input_from_global(&left, &sites, options).unwrap(); + let patched_right = patched_input_from_global(&right, &sites, options).unwrap(); + ( + sites, + left_mix, + right_mix, + left, + right, + patched_left, + patched_right, + ) } - /// All four engines must reproduce the pointwise product to an accuracy - /// consistent with the tolerance they were built and truncated at. - /// - /// The bound is shared: unlike the fixed-budget cases, nothing here forces - /// an arm to spend a budget it cannot afford, so every engine is expected to - /// land near the tolerance. It is `1e3 * rtol` for the same reason case 1 - /// uses that shape, the pointwise error of a norm-relative truncation is not - /// bounded by the tolerance itself. - /// - /// The four engines are expected to agree here, and in the case-5 sweep they - /// agree to every reported digit: at a tolerance nothing binds against, each - /// one computes the same product and the final budgeting truncates all of - /// them identically. So this test cannot tell the engines apart, which is why - /// it checks instead that they really ran, by requiring the patches to have - /// enough free sites for the per-patch product to be a sweep rather than the - /// single-site fallback. `elementwise::algorithms_are_distinguishable_under_ - /// forced_truncation` is what pins the engines apart, on the same code path. #[test] - fn all_engines_reproduce_the_pointwise_product() { - let (sites, f, g, fp, gp, box_l, rtol) = setup(6, 8); - println!("patches: f {} g {}", fp.len(), gp.len()); - assert!( - fp.len() > 1 || gp.len() > 1, - "the cap did not force a split, so this instance tests nothing" - ); - let deepest = fp - .projectors() - .chain(gp.projectors()) - .map(Projector::len) - .max() - .unwrap(); - assert!( - sites.len() - deepest >= 2, - "the deepest patch leaves {} free sites, so the per-patch products fall back \ - to the single-site path and no engine is exercised", - sites.len() - deepest - ); - for engine in [ - PatchedEngine::Naive, - PatchedEngine::ZipupTreetn, - PatchedEngine::FitTreetn, - PatchedEngine::Aci, - ] { - let h = patched_elementwise(&fp, &gp, &sites, product_options(engine, rtol)).unwrap(); - let err = max_rel_error_patched(&h, &sites, &f, &g, box_l, 128, 99).unwrap(); - let params = total_params(&h, &sites).unwrap(); - println!( - "{engine:?}: rel err {err:.3e}, {} patches, max bond {}, params {params}", - h.len(), - max_patch_bond(&h) - ); + fn bridge_preserves_values_and_site_indices() { + let (sites, _, _, left, _, _, _) = fixture(); + let bridged = tt_to_patch_train(&left, &sites).unwrap(); + let patched = PartitionedTT::from_subdomains(vec![SubDomainTT::from_tt(bridged)]).unwrap(); + let (_, subdomain) = patched.iter().next().unwrap(); + for sample in sample_grid_indices(left.len(), 32, 9) { + let bits = index_to_bits(sample, left.len()); + let fused: Vec<_> = bits.into_iter().map(|bit| bit * 3).collect(); assert!( - err.is_finite() && err < 1e3 * rtol, - "{engine:?}: rel err {err:e} exceeds {:e}", - 1e3 * rtol + (eval_patched(&patched, &sites, &fused).unwrap() - left.evaluate(&fused).unwrap()) + .abs() + < 1e-10 ); - assert!(params > 0); - assert!(!h.is_empty()); } - } - - /// The default construction of case 5, the norm-driven one, has to reproduce - /// the pointwise product just as the TCI-driven one does. - /// - /// Same instance, same tolerance and same bound as - /// `all_engines_reproduce_the_pointwise_product`, so the two paths are held to - /// one standard and the difference between them stays visible in the printed - /// patch counts rather than in what they are allowed to return. The cap is - /// tight enough that the splitting really runs, and the free-site check is the - /// same one: it is what says the per-patch products were sweeps rather than the - /// single-site fallback, so the engines were exercised. Two engines are run - /// here, one SVD-based and the interpolating one, which are the two kinds of - /// per-patch product; the four-engine sweep on this code path is the test - /// above. - #[test] - fn norm_driven_path_reproduces_the_pointwise_product() { - let (sites, f, g, fp, gp, box_l, rtol) = setup_norm(6, 8); - println!("patches: f {} g {}", fp.len(), gp.len()); - assert!( - fp.len() > 1 || gp.len() > 1, - "the cap did not force a split, so this instance tests nothing" - ); - let deepest = fp - .projectors() - .chain(gp.projectors()) - .map(Projector::len) - .max() - .unwrap(); - assert!( - sites.len() - deepest >= 2, - "the deepest patch leaves {} free sites, so the per-patch products fall back \ - to the single-site path and no engine is exercised", - sites.len() - deepest - ); - for engine in [PatchedEngine::FitTreetn, PatchedEngine::Aci] { - let h = patched_elementwise(&fp, &gp, &sites, product_options(engine, rtol)).unwrap(); - let err = max_rel_error_patched(&h, &sites, &f, &g, box_l, 128, 99).unwrap(); - let params = total_params(&h, &sites).unwrap(); - println!( - "{engine:?}: rel err {err:.3e}, {} patches, max bond {}, params {params}", - h.len(), - max_patch_bond(&h) - ); - assert!( - err.is_finite() && err < 1e3 * rtol, - "{engine:?}: rel err {err:e} exceeds {:e}", - 1e3 * rtol - ); - assert!(params > 0); - assert!(!h.is_empty()); + for site in &sites { + assert!(subdomain + .data() + .site_indices() + .iter() + .flatten() + .any(|index| index == site)); } } - /// The anisotropic spike family, the default family of case 5, on the default - /// input construction. - /// - /// Small and deliberately well conditioned: four spikes of minor width 0.25 on - /// a box of half-width 1 at `R` = 6, so the grid resolves a spike to eight - /// steps and the sampled reference is not a field of zeros, which it would be - /// if this test copied the sweep's own spacing-to-width ratio at this bit - /// count. What it checks is the same thing the smooth tests check on the same - /// code path, that every engine reproduces the pointwise product at the - /// tolerance, with the cap tight enough that the splitting really runs and the - /// deepest patch still leaves the per-patch products a sweep to do. #[test] - fn aniso_family_products_reproduce_the_pointwise_product() { - use crate::gaussian::{to_quantics_fused_tt_field, AnisoMixture2D}; - - let (r, box_l, chi_p) = (6usize, 1.0, 8usize); - let f = AnisoMixture2D::random(4, box_l, 0.25, 8.0, 1); - let g = AnisoMixture2D::random(4, box_l, 0.25, 8.0, 2); - let sites = fused_site_indices(r); - let rtol = 1e-8; - let options = NormPatchedInputOptions { - rtol, - max_bond_dim: chi_p, - strategy: PatchSplitStrategy::default(), - }; - let (fa, _) = to_quantics_fused_tt_field(&f, r, box_l, rtol, 256).unwrap(); - let (gb, _) = to_quantics_fused_tt_field(&g, r, box_l, rtol, 256).unwrap(); - let fp = patched_input_from_global(&fa, &sites, options).unwrap(); - let gp = patched_input_from_global(&gb, &sites, options).unwrap(); - println!("patches: f {} g {}", fp.len(), gp.len()); - assert!( - fp.len() > 1 || gp.len() > 1, - "the cap did not force a split, so this instance tests nothing" - ); - let deepest = fp - .projectors() - .chain(gp.projectors()) - .map(Projector::len) - .max() - .unwrap(); - assert!( - sites.len() - deepest >= 2, - "the deepest patch leaves {} free sites, so the per-patch products fall back \ - to the single-site path and no engine is exercised", - sites.len() - deepest - ); - for engine in [ - PatchedEngine::Naive, - PatchedEngine::ZipupTreetn, - PatchedEngine::FitTreetn, - PatchedEngine::Aci, + fn fit_and_aci_patched_products_match_the_reference() { + let (sites, left_mix, right_mix, left, right, patched_left, patched_right) = fixture(); + for (engine, global_algo, aci_tolerance) in [ + ( + PatchedEngine::FitTreetn, + ElementwiseAlgo::Fit, + AciTolerance::Absolute, + ), + ( + PatchedEngine::Aci, + ElementwiseAlgo::Aci, + AciTolerance::ScaleRelative, + ), ] { - let (h, stats) = - patched_elementwise_with_stats(&fp, &gp, &sites, product_options(engine, rtol)) + let global = + elementwise_product(global_algo, &left, &right, 1e-8, 256, aci_tolerance).unwrap(); + let patched = patched_elementwise( + &patched_left, + &patched_right, + &sites, + PatchedProductOptions { + engine, + product_tol: 1e-10, + product_max_bond_dim: 256, + rtol: 1e-8, + max_bond_dim: crate::gaussian_input::PATCH_CAP, + }, + ) + .unwrap(); + let global_error = + max_rel_error_vs_product(&global, &left_mix, &right_mix, 6, 1.0, 64, 17); + let patched_error = + max_rel_error_patched(&patched, &sites, &left_mix, &right_mix, 1.0, 64, 17) .unwrap(); - let err = max_rel_error_patched(&h, &sites, &f, &g, box_l, 128, 99).unwrap(); - println!( - "{engine:?}: rel err {err:.3e}, {} patches, {} pairs, max bond {}", - h.len(), - stats.n_pairs, - max_patch_bond(&h) - ); assert!( - err.is_finite() && err < 1e3 * rtol, - "{engine:?}: rel err {err:e} exceeds {:e}", - 1e3 * rtol + global_error < 1e-4, + "{engine:?}: global error={global_error:.3e}" ); - // The breakdown has to describe the run that produced this product. - assert!(stats.n_pairs >= h.len()); - assert!(stats.pairs_secs > 0.0 && stats.truncate_secs > 0.0); - assert!(total_params(&h, &sites).unwrap() > 0); - } - } - - /// The bridge that the norm-driven path goes through must copy the train - /// rather than change it, and it must land on the site indices this module - /// hands out: a bridge that minted its own indices would produce patches that - /// can never be paired with another input's patches, since projector - /// compatibility is decided by index identity. - #[test] - fn the_bridge_preserves_values_and_site_indices() { - use crate::gaussian::to_quantics_fused_tt; - - let (r, box_l) = (5, 3.0); - let mix = GaussianMixture2D::random(3, box_l, (0.5, 8.0), 4); - let sites = fused_site_indices(r); - let (tt, _) = to_quantics_fused_tt(&mix, r, box_l, 1e-10, 256).unwrap(); - let bridged = tt_to_patch_train(&tt, &sites).unwrap(); - - // One subdomain over the whole domain, so a full projector turns the - // restriction into an evaluation of the bridged train itself. - let whole = PartitionedTT::from_subdomain(SubDomainTT::from_tt(bridged)).unwrap(); - for &(ix, iy) in &[(0u64, 0u64), (5, 27), (31, 1), (16, 16)] { - let xb = index_to_bits(ix, r); - let yb = index_to_bits(iy, r); - let fused: Vec = (0..r).map(|n| xb[n] + 2 * yb[n]).collect(); - let got = eval_patched(&whole, &sites, &fused).unwrap(); - let want = tt.evaluate(&fused).unwrap(); assert!( - (got - want).abs() < 1e-12 * want.abs().max(1e-12), - "bridge changed the value at ({ix},{iy}): got {got:e} want {want:e}" + patched_error < 1e-4, + "{engine:?}: patched error={patched_error:.3e}" ); - } - } - - /// The patched product must agree with the global product of the same - /// instance, which is the statement that the patching is a representation - /// change and not a different function. - #[test] - fn patched_product_agrees_with_the_global_product() { - use crate::gaussian::to_quantics_fused_tt; - - let (sites, f, g, fp, gp, box_l, rtol) = setup(6, 8); - let r = sites.len(); - let h = patched_elementwise( - &fp, - &gp, - &sites, - product_options(PatchedEngine::FitTreetn, rtol), - ) - .unwrap(); - - let (fa, _) = to_quantics_fused_tt(&f, r, box_l, rtol, 256).unwrap(); - let (gb, _) = to_quantics_fused_tt(&g, r, box_l, rtol, 256).unwrap(); - let global = elementwise_product( - ElementwiseAlgo::Fit, - &fa, - &gb, - rtol, - 256, - AciTolerance::Absolute, - ) - .unwrap(); - - let mut worst = 0.0f64; - let mut scale = 0.0f64; - for &ix in &sample_grid_indices(r, 64, 5) { - for &iy in &sample_grid_indices(r, 4, 6) { - let xb = index_to_bits(ix, r); - let yb = index_to_bits(iy, r); - let fused: Vec = (0..r).map(|n| xb[n] + 2 * yb[n]).collect(); - let a = eval_patched(&h, &sites, &fused).unwrap(); - let b = global.evaluate(&fused).unwrap(); - worst = worst.max((a - b).abs()); - scale = scale.max(b.abs()); - } - } - println!("max |patched - global| = {worst:.3e} on a scale of {scale:.3e}"); - assert!( - worst < 1e-4 * scale.max(1e-12), - "patched and global disagree" - ); - } - - /// A patch whose norm is negligible against its volume share of the budget - /// is dropped, and the representation then evaluates to zero there, while the - /// patches that carry the function survive. - /// - /// The instance is one Gaussian sitting in the lower-left quadrant, squared: - /// the product is of order one there and around `1e-56` in the opposite - /// corner, so the budgeting has both kinds of patch to decide about. Both - /// halves of the behaviour are pinned here, patches disappearing where the - /// function is negligible and `eval_patched` answering zero exactly there, and - /// the surviving patches still reproducing the product where it is not. - /// - /// The width is chosen so that the Gaussian is still visible to a handful of - /// random samples over the whole box. A much narrower one is a genuinely - /// sparse function, and `adaptiveinterpolate` then declares the top patch zero - /// without sampling further, as its documentation says it will unless it is - /// given pivots in a nonzero region, which would make this a test of that - /// behaviour instead. - #[test] - fn negligible_patches_are_dropped_and_evaluate_to_zero() { - let (r, box_l) = (6, 4.0); - let sites = fused_site_indices(r); - let corner = GaussianMixture2D { - weights: vec![1.0], - alphas: vec![2.0], - centers: vec![(-box_l / 2.0, -box_l / 2.0)], - }; - let options = |seed| PatchedInputOptions { - abs_tol: 1e-8, - max_bond_dim: 8, - max_iter: 200, - seed, - }; - let fp = patched_input(&corner, &sites, box_l, options(1)).unwrap(); - let gp = patched_input(&corner, &sites, box_l, options(2)).unwrap(); - - let h = patched_elementwise( - &fp, - &gp, - &sites, - product_options(PatchedEngine::ZipupTreetn, 1e-8), - ) - .unwrap(); - println!( - "patches: f {} g {}, pairs kept after budgeting {}", - fp.len(), - gp.len(), - h.len() - ); - assert!( - h.len() < fp.len() * gp.len(), - "no patch was dropped from a product that vanishes over most of the box" - ); - assert!(!h.is_empty(), "every patch was dropped, including the peak"); - - // The far corner of the box is where the product is negligible, so its - // patches are gone and the representation answers exactly zero. That is - // also the right answer to about machine precision. - let mut dropped = 0usize; - for &ix in &sample_grid_indices(r, 32, 11) { - let far = (1u64 << (r - 1)) | (ix >> 1); - let xb = index_to_bits(far, r); - let fused: Vec = (0..r).map(|n| xb[n] * 3).collect(); - let got = eval_patched(&h, &sites, &fused).unwrap(); - assert!(got.abs() < 1e-12, "expected a dropped patch, got {got:e}"); - if got == 0.0 { - dropped += 1; - } - } - assert!(dropped > 0, "no sampled point fell in a dropped patch"); - - // The peak is in a surviving patch and is still reproduced there. - let peak = 1u64 << (r - 2); - let bits = index_to_bits(peak, r); - let fused: Vec = (0..r).map(|n| bits[n] * 3).collect(); - let x = grid_coord(peak, r, box_l); - let want = corner.eval(x, x).powi(2); - let got = eval_patched(&h, &sites, &fused).unwrap(); - println!("at the peak: {got:.6e} against {want:.6e}"); - assert!( - want > 1e-3, - "the chosen point is not the peak of the product" - ); - assert!((got - want).abs() < 1e-6 * want, "the peak patch was lost"); - } - - /// The fused layout of `patched_input` has to be the layout the rest of the - /// benchmark uses, or the patched arms would silently interpolate a - /// transposed function. - #[test] - fn fused_coordinates_match_the_benchmark_layout() { - let (r, box_l) = (5, 3.0); - for &(ix, iy) in &[(0u64, 0u64), (5, 27), (31, 1), (16, 16)] { - let xb = index_to_bits(ix, r); - let yb = index_to_bits(iy, r); - let fused: Vec = (0..r).map(|n| xb[n] + 2 * yb[n]).collect(); - let (x, y) = fused_to_coords(&fused, r, box_l); - assert_eq!((x, y), (grid_coord(ix, r, box_l), grid_coord(iy, r, box_l))); + assert!(max_patch_bond(&patched) <= crate::gaussian_input::PATCH_CAP); } } } diff --git a/src/patched_mpo.rs b/src/patched_mpo.rs index a6f8fa9..741bd18 100644 --- a/src/patched_mpo.rs +++ b/src/patched_mpo.rs @@ -9,8 +9,8 @@ use tensor4all_treetn::contraction::ContractionOptions as TreeContractOptions; use crate::mpo_contract::{mpo_to_tensortrain, tensortrain_to_mpo}; -fn itensor_cutoff_policy(cutoff: f64) -> SvdTruncationPolicy { - SvdTruncationPolicy::new(cutoff) +fn itensor_cutoff_policy(rtol: f64) -> SvdTruncationPolicy { + SvdTruncationPolicy::new(rtol * rtol) .with_relative() .with_squared_values() .with_discarded_tail_sum() @@ -98,6 +98,29 @@ pub fn tensortrain_n_params(tt: &TensorTrain) -> usize { .sum() } +/// Total stored scalar entries across a patched chain TreeTN. +pub fn partitioned_treetn_n_params(output: &tree::PartitionedTreeTN) -> usize { + output + .values() + .map(|subdomain| { + let network = subdomain.data(); + network + .node_names() + .into_iter() + .filter_map(|node| network.node_index(&node)) + .filter_map(|node| network.tensor(node)) + .map(|tensor| { + tensor + .indices() + .iter() + .map(|index| index.dim) + .product::() + }) + .sum::() + }) + .sum() +} + impl PatchedMpoPair { /// Build both patched representations from exactly the same MPO cores and indices. pub fn new( diff --git a/src/scalar.rs b/src/scalar.rs index 21d2655..b938d6f 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -1,6 +1,6 @@ //! The scalar types the benchmark's tensor trains are built on. //! -//! Case 1 runs on `Complex64` (a Fourier series) and case 3 on `f64` (a real +//! Case 1 runs on `Complex64` (a Fourier series) and case 2 on `f64` (a real //! Gaussian mixture), and both go through the same Hadamard code, so that code //! is generic over this trait. //! diff --git a/uv.lock b/uv.lock deleted file mode 100644 index be2135b..0000000 --- a/uv.lock +++ /dev/null @@ -1,595 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.11" -resolution-markers = [ - "python_full_version >= '3.12'", - "python_full_version < '3.12'", -] - -[[package]] -name = "contourpy" -version = "1.3.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, - { name = "numpy", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, - { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, - { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, - { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, - { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, - { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, - { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, - { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, - { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z" }, - { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z" }, - { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z" }, - { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, - { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, - { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, - { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, - { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, - { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, - { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, - { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, - { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, - { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, - { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, - { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, - { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, - { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, - { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, - { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, - { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, - { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, - { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, - { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, - { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, - { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, - { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, - { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, - { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, - { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, - { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, - { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, - { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, - { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, - { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, - { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, - { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, - { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, - { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, - { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, - { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, - { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, - { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, - { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, - { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, - { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, - { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, - { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, - { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, - { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, - { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, - { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, - { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, - { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, - { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, - { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, - { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, - { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z" }, -] - -[[package]] -name = "cycler" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, -] - -[[package]] -name = "fonttools" -version = "4.63.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/84/69/c97f2c18e0db87d2c7b15da1974dace76ae938f1cfa22e2727a648b7ed43/fonttools-4.63.0.tar.gz", hash = "sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0", size = 3597189, upload-time = "2026-05-14T12:04:30.958Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/75/2b/a7f1545bdf5da69c4bda0cea2a5781f0ad2a6623e0277267672db43c5fe6/fonttools-4.63.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f", size = 2881793, upload-time = "2026-05-14T12:02:56.645Z" }, - { url = "https://files.pythonhosted.org/packages/49/50/965308c703f085f225db2886813b27e015b8b3438c350b22dd65b52c2a2c/fonttools-4.63.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9", size = 2428130, upload-time = "2026-05-14T12:02:58.891Z" }, - { url = "https://files.pythonhosted.org/packages/d8/38/6937fbd7f2dc3a6b48725851bc2c15ec949b9af14d9bbcb5fe83cdf9bdf9/fonttools-4.63.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b", size = 5111952, upload-time = "2026-05-14T12:03:01.263Z" }, - { url = "https://files.pythonhosted.org/packages/0b/43/a81f20050a3115b57d62c8e781446949512eac36690dc384ccea65ff4cc1/fonttools-4.63.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18", size = 5082308, upload-time = "2026-05-14T12:03:03.211Z" }, - { url = "https://files.pythonhosted.org/packages/67/00/cdd9d4944ca6ae280d01e69cc37bde3bf663630b837a6fc6d2cd65d80e0e/fonttools-4.63.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0", size = 5087932, upload-time = "2026-05-14T12:03:05.147Z" }, - { url = "https://files.pythonhosted.org/packages/f5/f1/0aa0dbea778c75adbef223c42019fd47d22262b905974d62d829545d485f/fonttools-4.63.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007", size = 5213271, upload-time = "2026-05-14T12:03:07.238Z" }, - { url = "https://files.pythonhosted.org/packages/a8/99/253e4056e1f0e67b9390125a154b73b5eb73ad521bece95c004858fdeec2/fonttools-4.63.0-cp311-cp311-win32.whl", hash = "sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb", size = 2304473, upload-time = "2026-05-14T12:03:09.271Z" }, - { url = "https://files.pythonhosted.org/packages/08/60/defa5e69641db890a63be281f41345f4c33b157824eaf0b9fad3e08b0dcb/fonttools-4.63.0-cp311-cp311-win_amd64.whl", hash = "sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c", size = 2356389, upload-time = "2026-05-14T12:03:11.53Z" }, - { url = "https://files.pythonhosted.org/packages/08/ef/b3c6b9b5be2f82416d73fe2ed2e96e2793cd80e7510bd6a17ca79cdd88ec/fonttools-4.63.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02", size = 2881131, upload-time = "2026-05-14T12:03:13.386Z" }, - { url = "https://files.pythonhosted.org/packages/44/a0/c815bea63117fa63e4e1c01f8a1110d2112fa003f838e6467094ec2432ce/fonttools-4.63.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0", size = 2426704, upload-time = "2026-05-14T12:03:15.801Z" }, - { url = "https://files.pythonhosted.org/packages/44/04/0b91d8e916e92ad1fac9e4624760baf0fd5ff2ead614c2f68fb21373f03f/fonttools-4.63.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af", size = 5044298, upload-time = "2026-05-14T12:03:18.085Z" }, - { url = "https://files.pythonhosted.org/packages/77/c7/2342da9830e3e9d4870305ca5d2091d2a83284f2953079b7bdd3b5e029d8/fonttools-4.63.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8", size = 4999800, upload-time = "2026-05-14T12:03:20.161Z" }, - { url = "https://files.pythonhosted.org/packages/e6/6d/67fe16c48d7ce050979b33f47e0d28a318f02da030602e944c34f7a16ef3/fonttools-4.63.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b", size = 4982666, upload-time = "2026-05-14T12:03:22.87Z" }, - { url = "https://files.pythonhosted.org/packages/f2/00/3bbab338c07c71fa56269953845e92c951a61457bbbb0f1022551ea266d9/fonttools-4.63.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78", size = 5133598, upload-time = "2026-05-14T12:03:25.168Z" }, - { url = "https://files.pythonhosted.org/packages/62/f2/aa27c7f98db5b064883dadcc5283947e81e034de42e22a33675878d98b54/fonttools-4.63.0-cp312-cp312-win32.whl", hash = "sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263", size = 2292575, upload-time = "2026-05-14T12:03:27.496Z" }, - { url = "https://files.pythonhosted.org/packages/87/36/cccb9bc2a6ab63d1b2980374f0dca72ce95ae267c9b4cfe77455bb70d0d4/fonttools-4.63.0-cp312-cp312-win_amd64.whl", hash = "sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272", size = 2343211, upload-time = "2026-05-14T12:03:30.057Z" }, - { url = "https://files.pythonhosted.org/packages/0f/8d/d8fec3dcde2963f8c908fb315e5ff2cd0ac34f82394bbbf73a2aa5145ce3/fonttools-4.63.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd", size = 2876062, upload-time = "2026-05-14T12:03:32.554Z" }, - { url = "https://files.pythonhosted.org/packages/ef/71/d935dc54e4ff121bfdd11e08702db63a7e6f25af21d8a3d7b7212df53641/fonttools-4.63.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59", size = 2424594, upload-time = "2026-05-14T12:03:34.86Z" }, - { url = "https://files.pythonhosted.org/packages/8e/40/e76320afa1df918e146155ef239b1719ee266092e96f5423bfd075affba1/fonttools-4.63.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d", size = 5024840, upload-time = "2026-05-14T12:03:36.745Z" }, - { url = "https://files.pythonhosted.org/packages/ce/36/0b805d8c485f872f65a509cbe3b58a5d0d17bee855333b54a150c79d3061/fonttools-4.63.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68", size = 4975801, upload-time = "2026-05-14T12:03:38.833Z" }, - { url = "https://files.pythonhosted.org/packages/c8/26/2cee03d0aa083ab022da5c07aff9ed3f689da1defb81ad6917c9627896da/fonttools-4.63.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be", size = 4965009, upload-time = "2026-05-14T12:03:41.494Z" }, - { url = "https://files.pythonhosted.org/packages/7e/48/cc4b66d9058c0d0982c833fad10127c4b0e9324606aafa41382295ca4102/fonttools-4.63.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27", size = 5105892, upload-time = "2026-05-14T12:03:43.525Z" }, - { url = "https://files.pythonhosted.org/packages/d8/1f/a98a30a814b9ddef3a2e706025f90b9e0bc94890e6cb15254bc86547d11a/fonttools-4.63.0-cp313-cp313-win32.whl", hash = "sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380", size = 2291313, upload-time = "2026-05-14T12:03:45.594Z" }, - { url = "https://files.pythonhosted.org/packages/92/46/5177b01f3b4abfdd4409f31cca4ab279c9343a26efbe9ec78c97fc612e02/fonttools-4.63.0-cp313-cp313-win_amd64.whl", hash = "sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b", size = 2342299, upload-time = "2026-05-14T12:03:47.414Z" }, - { url = "https://files.pythonhosted.org/packages/27/d2/23d25e3f247b328be58d04a4c9f894178a0d1eda7d42867cfb388adaf416/fonttools-4.63.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745", size = 2875338, upload-time = "2026-05-14T12:03:50.052Z" }, - { url = "https://files.pythonhosted.org/packages/cd/58/7dfa0c761cb3b2964e2a84c4dc986c926a87de0cb9fb60d5b28ded3f2914/fonttools-4.63.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03", size = 2422661, upload-time = "2026-05-14T12:03:52.154Z" }, - { url = "https://files.pythonhosted.org/packages/dd/87/64cfa18a7a1621d17b7f4502b2b0ed8a135a90c3db51ea590ee99043e76b/fonttools-4.63.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49", size = 5010526, upload-time = "2026-05-14T12:03:54.647Z" }, - { url = "https://files.pythonhosted.org/packages/36/e1/a8933a72c45a87177fbde2696e0d0755c8c9062f8c077a961c6215fa27b1/fonttools-4.63.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b", size = 4923946, upload-time = "2026-05-14T12:03:56.984Z" }, - { url = "https://files.pythonhosted.org/packages/27/60/872e6e233b8c5e8b41413796ff18b7fe479661bd40147e071b450dfad7a1/fonttools-4.63.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6", size = 4962489, upload-time = "2026-05-14T12:03:59.443Z" }, - { url = "https://files.pythonhosted.org/packages/30/c4/83c24f2ec38b90cfda84bf4b1a1f49df80e84a1db4e7ac6e0d41bf23bc39/fonttools-4.63.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4", size = 5071870, upload-time = "2026-05-14T12:04:02.122Z" }, - { url = "https://files.pythonhosted.org/packages/de/40/3ae22b60ff1d41ce0bd044b31238cdc72cef99f28b976f1e128ebd618c9b/fonttools-4.63.0-cp314-cp314-win32.whl", hash = "sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616", size = 2295026, upload-time = "2026-05-14T12:04:04.47Z" }, - { url = "https://files.pythonhosted.org/packages/c3/d4/98078064ccc76b45cb0f6c002452011e93c4bd26f6850344f0951cc1fe89/fonttools-4.63.0-cp314-cp314-win_amd64.whl", hash = "sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5", size = 2347454, upload-time = "2026-05-14T12:04:06.752Z" }, - { url = "https://files.pythonhosted.org/packages/49/4e/652d1580c5f4e39f7d103b0c793e4773129ad633dce4addd0cf4dfebde02/fonttools-4.63.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001", size = 2958152, upload-time = "2026-05-14T12:04:08.706Z" }, - { url = "https://files.pythonhosted.org/packages/0e/55/ad864c9a9b219f552eb46b32cd7906c466e5a578ba0c3abfcc0fe7413eb6/fonttools-4.63.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e", size = 2460809, upload-time = "2026-05-14T12:04:10.783Z" }, - { url = "https://files.pythonhosted.org/packages/ea/2b/0aa8db70f18cf52e49b4ed5ecec68547f981160bf5ded3b5aed6faa0a6f9/fonttools-4.63.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096", size = 5148649, upload-time = "2026-05-14T12:04:12.747Z" }, - { url = "https://files.pythonhosted.org/packages/7f/63/18e4369c25043096f1048e0c9915951adc4f842bd81c6b18155824d6fa99/fonttools-4.63.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f", size = 4932147, upload-time = "2026-05-14T12:04:14.806Z" }, - { url = "https://files.pythonhosted.org/packages/a1/3f/67f3eac2ffd8a98446c5022f8ed3864eac878a5ff7af8df4c8286dba16cc/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40", size = 5027237, upload-time = "2026-05-14T12:04:17.675Z" }, - { url = "https://files.pythonhosted.org/packages/1a/ba/4e6214cb38a7b04779e97bb7636de9a5c7f20af7018d03dee0b64c08510a/fonttools-4.63.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196", size = 5053933, upload-time = "2026-05-14T12:04:20.818Z" }, - { url = "https://files.pythonhosted.org/packages/34/3b/214dcc19ee31d3d38fb5ad2755c11ef0514e5dc300bbaf41c0b69f393799/fonttools-4.63.0-cp314-cp314t-win32.whl", hash = "sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8", size = 2359326, upload-time = "2026-05-14T12:04:24.22Z" }, - { url = "https://files.pythonhosted.org/packages/dd/1e/3ff1a9b523058c2eeb6a9d50f5574e2a738200d0d94107d5bc4105e8da3f/fonttools-4.63.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419", size = 2425829, upload-time = "2026-05-14T12:04:26.829Z" }, - { url = "https://files.pythonhosted.org/packages/2c/47/c99d5268f354002ce80f8d029cd9d7d872969da1de8b93d32de4dc56d6f4/fonttools-4.63.0-py3-none-any.whl", hash = "sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d", size = 1164562, upload-time = "2026-05-14T12:04:29.092Z" }, -] - -[[package]] -name = "kiwisolver" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/67/9c61eccb13f0bdca9307614e782fec49ffdde0f7a2314935d489fa93cd9c/kiwisolver-1.5.0.tar.gz", hash = "sha256:d4193f3d9dc3f6f79aaed0e5637f45d98850ebf01f7ca20e69457f3e8946b66a", size = 103482, upload-time = "2026-03-09T13:15:53.382Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/dd/a495a9c104be1c476f0386e714252caf2b7eca883915422a64c50b88c6f5/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9eed0f7edbb274413b6ee781cca50541c8c0facd3d6fd289779e494340a2b85c", size = 122798, upload-time = "2026-03-09T13:12:58.963Z" }, - { url = "https://files.pythonhosted.org/packages/11/60/37b4047a2af0cf5ef6d8b4b26e91829ae6fc6a2d1f74524bcb0e7cd28a32/kiwisolver-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c4923e404d6bcd91b6779c009542e5647fef32e4a5d75e115e3bbac6f2335eb", size = 66216, upload-time = "2026-03-09T13:13:00.155Z" }, - { url = "https://files.pythonhosted.org/packages/0a/aa/510dc933d87767584abfe03efa445889996c70c2990f6f87c3ebaa0a18c5/kiwisolver-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac", size = 63911, upload-time = "2026-03-09T13:13:01.671Z" }, - { url = "https://files.pythonhosted.org/packages/80/46/bddc13df6c2a40741e0cc7865bb1c9ed4796b6760bd04ce5fae3928ef917/kiwisolver-1.5.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2517e24d7315eb51c10664cdb865195df38ab74456c677df67bb47f12d088a27", size = 1438209, upload-time = "2026-03-09T13:13:03.385Z" }, - { url = "https://files.pythonhosted.org/packages/fd/d6/76621246f5165e5372f02f5e6f3f48ea336a8f9e96e43997d45b240ed8cd/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff710414307fefa903e0d9bdf300972f892c23477829f49504e59834f4195398", size = 1248888, upload-time = "2026-03-09T13:13:05.231Z" }, - { url = "https://files.pythonhosted.org/packages/b2/c1/31559ec6fb39a5b48035ce29bb63ade628f321785f38c384dee3e2c08bc1/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6176c1811d9d5a04fa391c490cc44f451e240697a16977f11c6f722efb9041db", size = 1266304, upload-time = "2026-03-09T13:13:06.743Z" }, - { url = "https://files.pythonhosted.org/packages/5e/ef/1cb8276f2d29cc6a41e0a042f27946ca347d3a4a75acf85d0a16aa6dcc82/kiwisolver-1.5.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50847dca5d197fcbd389c805aa1a1cf32f25d2e7273dc47ab181a517666b68cc", size = 1319650, upload-time = "2026-03-09T13:13:08.607Z" }, - { url = "https://files.pythonhosted.org/packages/4c/e4/5ba3cecd7ce6236ae4a80f67e5d5531287337d0e1f076ca87a5abe4cd5d0/kiwisolver-1.5.0-cp311-cp311-manylinux_2_39_riscv64.whl", hash = "sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679", size = 970949, upload-time = "2026-03-09T13:13:10.299Z" }, - { url = "https://files.pythonhosted.org/packages/5a/69/dc61f7ae9a2f071f26004ced87f078235b5507ab6e5acd78f40365655034/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f9f4121ec58628c96baa3de1a55a4e3a333c5102c8e94b64e23bf7b2083309", size = 2199125, upload-time = "2026-03-09T13:13:11.841Z" }, - { url = "https://files.pythonhosted.org/packages/e5/7b/abbe0f1b5afa85f8d084b73e90e5f801c0939eba16ac2e49af7c61a6c28d/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b7d335370ae48a780c6e6a6bbfa97342f563744c39c35562f3f367665f5c1de2", size = 2293783, upload-time = "2026-03-09T13:13:14.399Z" }, - { url = "https://files.pythonhosted.org/packages/8a/80/5908ae149d96d81580d604c7f8aefd0e98f4fd728cf172f477e9f2a81744/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:800ee55980c18545af444d93fdd60c56b580db5cc54867d8cbf8a1dc0829938c", size = 1960726, upload-time = "2026-03-09T13:13:16.047Z" }, - { url = "https://files.pythonhosted.org/packages/84/08/a78cb776f8c085b7143142ce479859cfec086bd09ee638a317040b6ef420/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c438f6ca858697c9ab67eb28246c92508af972e114cac34e57a6d4ba17a3ac08", size = 2464738, upload-time = "2026-03-09T13:13:17.897Z" }, - { url = "https://files.pythonhosted.org/packages/b1/e1/65584da5356ed6cb12c63791a10b208860ac40a83de165cb6a6751a686e3/kiwisolver-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8c63c91f95173f9c2a67c7c526b2cea976828a0e7fced9cdcead2802dc10f8a4", size = 2270718, upload-time = "2026-03-09T13:13:19.421Z" }, - { url = "https://files.pythonhosted.org/packages/be/6c/28f17390b62b8f2f520e2915095b3c94d88681ecf0041e75389d9667f202/kiwisolver-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:beb7f344487cdcb9e1efe4b7a29681b74d34c08f0043a327a74da852a6749e7b", size = 73480, upload-time = "2026-03-09T13:13:20.818Z" }, - { url = "https://files.pythonhosted.org/packages/d8/0e/2ee5debc4f77a625778fec5501ff3e8036fe361b7ee28ae402a485bb9694/kiwisolver-1.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:ad4ae4ffd1ee9cd11357b4c66b612da9888f4f4daf2f36995eda64bd45370cac", size = 64930, upload-time = "2026-03-09T13:13:21.997Z" }, - { url = "https://files.pythonhosted.org/packages/4d/b2/818b74ebea34dabe6d0c51cb1c572e046730e64844da6ed646d5298c40ce/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4e9750bc21b886308024f8a54ccb9a2cc38ac9fa813bf4348434e3d54f337ff9", size = 123158, upload-time = "2026-03-09T13:13:23.127Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d9/405320f8077e8e1c5c4bd6adc45e1e6edf6d727b6da7f2e2533cf58bff71/kiwisolver-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72ec46b7eba5b395e0a7b63025490d3214c11013f4aacb4f5e8d6c3041829588", size = 66388, upload-time = "2026-03-09T13:13:24.765Z" }, - { url = "https://files.pythonhosted.org/packages/99/9f/795fedf35634f746151ca8839d05681ceb6287fbed6cc1c9bf235f7887c2/kiwisolver-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ed3a984b31da7481b103f68776f7128a89ef26ed40f4dc41a2223cda7fb24819", size = 64068, upload-time = "2026-03-09T13:13:25.878Z" }, - { url = "https://files.pythonhosted.org/packages/c4/13/680c54afe3e65767bed7ec1a15571e1a2f1257128733851ade24abcefbcc/kiwisolver-1.5.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb5136fb5352d3f422df33f0c879a1b0c204004324150cc3b5e3c4f310c9049f", size = 1477934, upload-time = "2026-03-09T13:13:27.166Z" }, - { url = "https://files.pythonhosted.org/packages/c8/2f/cebfcdb60fd6a9b0f6b47a9337198bcbad6fbe15e68189b7011fd914911f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2af221f268f5af85e776a73d62b0845fc8baf8ef0abfae79d29c77d0e776aaf", size = 1278537, upload-time = "2026-03-09T13:13:28.707Z" }, - { url = "https://files.pythonhosted.org/packages/f2/0d/9b782923aada3fafb1d6b84e13121954515c669b18af0c26e7d21f579855/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b0f172dc8ffaccb8522d7c5d899de00133f2f1ca7b0a49b7da98e901de87bf2d", size = 1296685, upload-time = "2026-03-09T13:13:30.528Z" }, - { url = "https://files.pythonhosted.org/packages/27/70/83241b6634b04fe44e892688d5208332bde130f38e610c0418f9ede47ded/kiwisolver-1.5.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6ab8ba9152203feec73758dad83af9a0bbe05001eb4639e547207c40cfb52083", size = 1346024, upload-time = "2026-03-09T13:13:32.818Z" }, - { url = "https://files.pythonhosted.org/packages/e4/db/30ed226fb271ae1a6431fc0fe0edffb2efe23cadb01e798caeb9f2ceae8f/kiwisolver-1.5.0-cp312-cp312-manylinux_2_39_riscv64.whl", hash = "sha256:cdee07c4d7f6d72008d3f73b9bf027f4e11550224c7c50d8df1ae4a37c1402a6", size = 987241, upload-time = "2026-03-09T13:13:34.435Z" }, - { url = "https://files.pythonhosted.org/packages/ec/bd/c314595208e4c9587652d50959ead9e461995389664e490f4dce7ff0f782/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7c60d3c9b06fb23bd9c6139281ccbdc384297579ae037f08ae90c69f6845c0b1", size = 2227742, upload-time = "2026-03-09T13:13:36.4Z" }, - { url = "https://files.pythonhosted.org/packages/c1/43/0499cec932d935229b5543d073c2b87c9c22846aab48881e9d8d6e742a2d/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e315e5ec90d88e140f57696ff85b484ff68bb311e36f2c414aa4286293e6dee0", size = 2323966, upload-time = "2026-03-09T13:13:38.204Z" }, - { url = "https://files.pythonhosted.org/packages/3d/6f/79b0d760907965acfd9d61826a3d41f8f093c538f55cd2633d3f0db269f6/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:1465387ac63576c3e125e5337a6892b9e99e0627d52317f3ca79e6930d889d15", size = 1977417, upload-time = "2026-03-09T13:13:39.966Z" }, - { url = "https://files.pythonhosted.org/packages/ab/31/01d0537c41cb75a551a438c3c7a80d0c60d60b81f694dac83dd436aec0d0/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:530a3fd64c87cffa844d4b6b9768774763d9caa299e9b75d8eca6a4423b31314", size = 2491238, upload-time = "2026-03-09T13:13:41.698Z" }, - { url = "https://files.pythonhosted.org/packages/e4/34/8aefdd0be9cfd00a44509251ba864f5caf2991e36772e61c408007e7f417/kiwisolver-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d9daea4ea6b9be74fe2f01f7fbade8d6ffab263e781274cffca0dba9be9eec9", size = 2294947, upload-time = "2026-03-09T13:13:43.343Z" }, - { url = "https://files.pythonhosted.org/packages/ad/cf/0348374369ca588f8fe9c338fae49fa4e16eeb10ffb3d012f23a54578a9e/kiwisolver-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:f18c2d9782259a6dc132fdc7a63c168cbc74b35284b6d75c673958982a378384", size = 73569, upload-time = "2026-03-09T13:13:45.792Z" }, - { url = "https://files.pythonhosted.org/packages/28/26/192b26196e2316e2bd29deef67e37cdf9870d9af8e085e521afff0fed526/kiwisolver-1.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:f7c7553b13f69c1b29a5bde08ddc6d9d0c8bfb84f9ed01c30db25944aeb852a7", size = 64997, upload-time = "2026-03-09T13:13:46.878Z" }, - { url = "https://files.pythonhosted.org/packages/9d/69/024d6711d5ba575aa65d5538042e99964104e97fa153a9f10bc369182bc2/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:fd40bb9cd0891c4c3cb1ddf83f8bbfa15731a248fdc8162669405451e2724b09", size = 123166, upload-time = "2026-03-09T13:13:48.032Z" }, - { url = "https://files.pythonhosted.org/packages/ce/48/adbb40df306f587054a348831220812b9b1d787aff714cfbc8556e38fccd/kiwisolver-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0e1403fd7c26d77c1f03e096dc58a5c726503fa0db0456678b8668f76f521e3", size = 66395, upload-time = "2026-03-09T13:13:49.365Z" }, - { url = "https://files.pythonhosted.org/packages/a8/3a/d0a972b34e1c63e2409413104216cd1caa02c5a37cb668d1687d466c1c45/kiwisolver-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dda366d548e89a90d88a86c692377d18d8bd64b39c1fb2b92cb31370e2896bbd", size = 64065, upload-time = "2026-03-09T13:13:50.562Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0a/7b98e1e119878a27ba8618ca1e18b14f992ff1eda40f47bccccf4de44121/kiwisolver-1.5.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:332b4f0145c30b5f5ad9374881133e5aa64320428a57c2c2b61e9d891a51c2f3", size = 1477903, upload-time = "2026-03-09T13:13:52.084Z" }, - { url = "https://files.pythonhosted.org/packages/18/d8/55638d89ffd27799d5cc3d8aa28e12f4ce7a64d67b285114dbedc8ea4136/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c50b89ffd3e1a911c69a1dd3de7173c0cd10b130f56222e57898683841e4f96", size = 1278751, upload-time = "2026-03-09T13:13:54.673Z" }, - { url = "https://files.pythonhosted.org/packages/b8/97/b4c8d0d18421ecceba20ad8701358453b88e32414e6f6950b5a4bad54e65/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4db576bb8c3ef9365f8b40fe0f671644de6736ae2c27a2c62d7d8a1b4329f099", size = 1296793, upload-time = "2026-03-09T13:13:56.287Z" }, - { url = "https://files.pythonhosted.org/packages/c4/10/f862f94b6389d8957448ec9df59450b81bec4abb318805375c401a1e6892/kiwisolver-1.5.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0b85aad90cea8ac6797a53b5d5f2e967334fa4d1149f031c4537569972596cb8", size = 1346041, upload-time = "2026-03-09T13:13:58.269Z" }, - { url = "https://files.pythonhosted.org/packages/a3/6a/f1650af35821eaf09de398ec0bc2aefc8f211f0cda50204c9f1673741ba9/kiwisolver-1.5.0-cp313-cp313-manylinux_2_39_riscv64.whl", hash = "sha256:d36ca54cb4c6c4686f7cbb7b817f66f5911c12ddb519450bbe86707155028f87", size = 987292, upload-time = "2026-03-09T13:13:59.871Z" }, - { url = "https://files.pythonhosted.org/packages/de/19/d7fb82984b9238115fe629c915007be608ebd23dc8629703d917dbfaffd4/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:38f4a703656f493b0ad185211ccfca7f0386120f022066b018eb5296d8613e23", size = 2227865, upload-time = "2026-03-09T13:14:01.401Z" }, - { url = "https://files.pythonhosted.org/packages/7f/b9/46b7f386589fd222dac9e9de9c956ce5bcefe2ee73b4e79891381dda8654/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3ac2360e93cb41be81121755c6462cff3beaa9967188c866e5fce5cf13170859", size = 2324369, upload-time = "2026-03-09T13:14:02.972Z" }, - { url = "https://files.pythonhosted.org/packages/92/8b/95e237cf3d9c642960153c769ddcbe278f182c8affb20cecc1cc983e7cc5/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c95cab08d1965db3d84a121f1c7ce7479bdd4072c9b3dafd8fecce48a2e6b902", size = 1977989, upload-time = "2026-03-09T13:14:04.503Z" }, - { url = "https://files.pythonhosted.org/packages/1b/95/980c9df53501892784997820136c01f62bc1865e31b82b9560f980c0e649/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc20894c3d21194d8041a28b65622d5b86db786da6e3cfe73f0c762951a61167", size = 2491645, upload-time = "2026-03-09T13:14:06.106Z" }, - { url = "https://files.pythonhosted.org/packages/cb/32/900647fd0840abebe1561792c6b31e6a7c0e278fc3973d30572a965ca14c/kiwisolver-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7a32f72973f0f950c1920475d5c5ea3d971b81b6f0ec53b8d0a956cc965f22e0", size = 2295237, upload-time = "2026-03-09T13:14:08.891Z" }, - { url = "https://files.pythonhosted.org/packages/be/8a/be60e3bbcf513cc5a50f4a3e88e1dcecebb79c1ad607a7222877becaa101/kiwisolver-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bf3acf1419fa93064a4c2189ac0b58e3be7872bf6ee6177b0d4c63dc4cea276", size = 73573, upload-time = "2026-03-09T13:14:12.327Z" }, - { url = "https://files.pythonhosted.org/packages/4d/d2/64be2e429eb4fca7f7e1c52a91b12663aeaf25de3895e5cca0f47ef2a8d0/kiwisolver-1.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:fa8eb9ecdb7efb0b226acec134e0d709e87a909fa4971a54c0c4f6e88635484c", size = 64998, upload-time = "2026-03-09T13:14:13.469Z" }, - { url = "https://files.pythonhosted.org/packages/b0/69/ce68dd0c85755ae2de490bf015b62f2cea5f6b14ff00a463f9d0774449ff/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:db485b3847d182b908b483b2ed133c66d88d49cacf98fd278fadafe11b4478d1", size = 125700, upload-time = "2026-03-09T13:14:14.636Z" }, - { url = "https://files.pythonhosted.org/packages/74/aa/937aac021cf9d4349990d47eb319309a51355ed1dbdc9c077cdc9224cb11/kiwisolver-1.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:be12f931839a3bdfe28b584db0e640a65a8bcbc24560ae3fdb025a449b3d754e", size = 67537, upload-time = "2026-03-09T13:14:15.808Z" }, - { url = "https://files.pythonhosted.org/packages/ee/20/3a87fbece2c40ad0f6f0aefa93542559159c5f99831d596050e8afae7a9f/kiwisolver-1.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:16b85d37c2cbb3253226d26e64663f755d88a03439a9c47df6246b35defbdfb7", size = 65514, upload-time = "2026-03-09T13:14:18.035Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7f/f943879cda9007c45e1f7dba216d705c3a18d6b35830e488b6c6a4e7cdf0/kiwisolver-1.5.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4432b835675f0ea7414aab3d37d119f7226d24869b7a829caeab49ebda407b0c", size = 1584848, upload-time = "2026-03-09T13:14:19.745Z" }, - { url = "https://files.pythonhosted.org/packages/37/f8/4d4f85cc1870c127c88d950913370dd76138482161cd07eabbc450deff01/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b0feb50971481a2cc44d94e88bdb02cdd497618252ae226b8eb1201b957e368", size = 1391542, upload-time = "2026-03-09T13:14:21.54Z" }, - { url = "https://files.pythonhosted.org/packages/04/0b/65dd2916c84d252b244bd405303220f729e7c17c9d7d33dca6feeff9ffc4/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:56fa888f10d0f367155e76ce849fa1166fc9730d13bd2d65a2aa13b6f5424489", size = 1404447, upload-time = "2026-03-09T13:14:23.205Z" }, - { url = "https://files.pythonhosted.org/packages/39/5c/2606a373247babce9b1d056c03a04b65f3cf5290a8eac5d7bdead0a17e21/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:940dda65d5e764406b9fb92761cbf462e4e63f712ab60ed98f70552e496f3bf1", size = 1455918, upload-time = "2026-03-09T13:14:24.74Z" }, - { url = "https://files.pythonhosted.org/packages/d5/d1/c6078b5756670658e9192a2ef11e939c92918833d2745f85cd14a6004bdf/kiwisolver-1.5.0-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:89fc958c702ee9a745e4700378f5d23fddbc46ff89e8fdbf5395c24d5c1452a3", size = 1072856, upload-time = "2026-03-09T13:14:26.597Z" }, - { url = "https://files.pythonhosted.org/packages/cb/c8/7def6ddf16eb2b3741d8b172bdaa9af882b03c78e9b0772975408801fa63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9027d773c4ff81487181a925945743413f6069634d0b122d0b37684ccf4f1e18", size = 2333580, upload-time = "2026-03-09T13:14:28.237Z" }, - { url = "https://files.pythonhosted.org/packages/9e/87/2ac1fce0eb1e616fcd3c35caa23e665e9b1948bb984f4764790924594128/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:5b233ea3e165e43e35dba1d2b8ecc21cf070b45b65ae17dd2747d2713d942021", size = 2423018, upload-time = "2026-03-09T13:14:30.018Z" }, - { url = "https://files.pythonhosted.org/packages/67/13/c6700ccc6cc218716bfcda4935e4b2997039869b4ad8a94f364c5a3b8e63/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ce9bf03dad3b46408c08649c6fbd6ca28a9fce0eb32fdfffa6775a13103b5310", size = 2062804, upload-time = "2026-03-09T13:14:32.888Z" }, - { url = "https://files.pythonhosted.org/packages/1b/bd/877056304626943ff0f1f44c08f584300c199b887cb3176cd7e34f1515f1/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:fc4d3f1fb9ca0ae9f97b095963bc6326f1dbfd3779d6679a1e016b9baaa153d3", size = 2597482, upload-time = "2026-03-09T13:14:34.971Z" }, - { url = "https://files.pythonhosted.org/packages/75/19/c60626c47bf0f8ac5dcf72c6c98e266d714f2fbbfd50cf6dab5ede3aaa50/kiwisolver-1.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f443b4825c50a51ee68585522ab4a1d1257fac65896f282b4c6763337ac9f5d2", size = 2394328, upload-time = "2026-03-09T13:14:36.816Z" }, - { url = "https://files.pythonhosted.org/packages/47/84/6a6d5e5bb8273756c27b7d810d47f7ef2f1f9b9fd23c9ee9a3f8c75c9cef/kiwisolver-1.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:893ff3a711d1b515ba9da14ee090519bad4610ed1962fbe298a434e8c5f8db53", size = 68410, upload-time = "2026-03-09T13:14:38.695Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/060f45052f2a01ad5762c8fdecd6d7a752b43400dc29ff75cd47225a40fd/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8df31fe574b8b3993cc61764f40941111b25c2d9fea13d3ce24a49907cd2d615", size = 123231, upload-time = "2026-03-09T13:14:41.323Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a7/78da680eadd06ff35edef6ef68a1ad273bad3e2a0936c9a885103230aece/kiwisolver-1.5.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1d49a49ac4cbfb7c1375301cd1ec90169dfeae55ff84710d782260ce77a75a02", size = 66489, upload-time = "2026-03-09T13:14:42.534Z" }, - { url = "https://files.pythonhosted.org/packages/49/b2/97980f3ad4fae37dd7fe31626e2bf75fbf8bdf5d303950ec1fab39a12da8/kiwisolver-1.5.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0cbe94b69b819209a62cb27bdfa5dc2a8977d8de2f89dfd97ba4f53ed3af754e", size = 64063, upload-time = "2026-03-09T13:14:44.759Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f9/b06c934a6aa8bc91f566bd2a214fd04c30506c2d9e2b6b171953216a65b6/kiwisolver-1.5.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80aa065ffd378ff784822a6d7c3212f2d5f5e9c3589614b5c228b311fd3063ac", size = 1475913, upload-time = "2026-03-09T13:14:46.247Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f0/f768ae564a710135630672981231320bc403cf9152b5596ec5289de0f106/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e7f886f47ab881692f278ae901039a234e4025a68e6dfab514263a0b1c4ae05", size = 1282782, upload-time = "2026-03-09T13:14:48.458Z" }, - { url = "https://files.pythonhosted.org/packages/e2/9f/1de7aad00697325f05238a5f2eafbd487fb637cc27a558b5367a5f37fb7f/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5060731cc3ed12ca3a8b57acd4aeca5bbc2f49216dd0bec1650a1acd89486bcd", size = 1300815, upload-time = "2026-03-09T13:14:50.721Z" }, - { url = "https://files.pythonhosted.org/packages/5a/c2/297f25141d2e468e0ce7f7a7b92e0cf8918143a0cbd3422c1ad627e85a06/kiwisolver-1.5.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a4aa69609f40fce3cbc3f87b2061f042eee32f94b8f11db707b66a26461591a", size = 1347925, upload-time = "2026-03-09T13:14:52.304Z" }, - { url = "https://files.pythonhosted.org/packages/b9/d3/f4c73a02eb41520c47610207b21afa8cdd18fdbf64ffd94674ae21c4812d/kiwisolver-1.5.0-cp314-cp314-manylinux_2_39_riscv64.whl", hash = "sha256:d168fda2dbff7b9b5f38e693182d792a938c31db4dac3a80a4888de603c99554", size = 991322, upload-time = "2026-03-09T13:14:54.637Z" }, - { url = "https://files.pythonhosted.org/packages/7b/46/d3f2efef7732fcda98d22bf4ad5d3d71d545167a852ca710a494f4c15343/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:413b820229730d358efd838ecbab79902fe97094565fdc80ddb6b0a18c18a581", size = 2232857, upload-time = "2026-03-09T13:14:56.471Z" }, - { url = "https://files.pythonhosted.org/packages/3f/ec/2d9756bf2b6d26ae4349b8d3662fb3993f16d80c1f971c179ce862b9dbae/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5124d1ea754509b09e53738ec185584cc609aae4a3b510aaf4ed6aa047ef9303", size = 2329376, upload-time = "2026-03-09T13:14:58.072Z" }, - { url = "https://files.pythonhosted.org/packages/8f/9f/876a0a0f2260f1bde92e002b3019a5fabc35e0939c7d945e0fa66185eb20/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e4415a8db000bf49a6dd1c478bf70062eaacff0f462b92b0ba68791a905861f9", size = 1982549, upload-time = "2026-03-09T13:14:59.668Z" }, - { url = "https://files.pythonhosted.org/packages/6c/4f/ba3624dfac23a64d54ac4179832860cb537c1b0af06024936e82ca4154a0/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d618fd27420381a4f6044faa71f46d8bfd911bd077c555f7138ed88729bfbe79", size = 2494680, upload-time = "2026-03-09T13:15:01.364Z" }, - { url = "https://files.pythonhosted.org/packages/39/b7/97716b190ab98911b20d10bf92eca469121ec483b8ce0edd314f51bc85af/kiwisolver-1.5.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5092eb5b1172947f57d6ea7d89b2f29650414e4293c47707eb499ec07a0ac796", size = 2297905, upload-time = "2026-03-09T13:15:03.925Z" }, - { url = "https://files.pythonhosted.org/packages/a3/36/4e551e8aa55c9188bca9abb5096805edbf7431072b76e2298e34fd3a3008/kiwisolver-1.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:d76e2d8c75051d58177e762164d2e9ab92886534e3a12e795f103524f221dd8e", size = 75086, upload-time = "2026-03-09T13:15:07.775Z" }, - { url = "https://files.pythonhosted.org/packages/70/15/9b90f7df0e31a003c71649cf66ef61c3c1b862f48c81007fa2383c8bd8d7/kiwisolver-1.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:fa6248cd194edff41d7ea9425ced8ca3a6f838bfb295f6f1d6e6bb694a8518df", size = 66577, upload-time = "2026-03-09T13:15:09.139Z" }, - { url = "https://files.pythonhosted.org/packages/17/01/7dc8c5443ff42b38e72731643ed7cf1ed9bf01691ae5cdca98501999ed83/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d1ffeb80b5676463d7a7d56acbe8e37a20ce725570e09549fe738e02ca6b7e1e", size = 125794, upload-time = "2026-03-09T13:15:10.525Z" }, - { url = "https://files.pythonhosted.org/packages/46/8a/b4ebe46ebaac6a303417fab10c2e165c557ddaff558f9699d302b256bc53/kiwisolver-1.5.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc4d8e252f532ab46a1de9349e2d27b91fce46736a9eedaa37beaca66f574ed4", size = 67646, upload-time = "2026-03-09T13:15:12.016Z" }, - { url = "https://files.pythonhosted.org/packages/60/35/10a844afc5f19d6f567359bf4789e26661755a2f36200d5d1ed8ad0126e5/kiwisolver-1.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6783e069732715ad0c3ce96dbf21dbc2235ab0593f2baf6338101f70371f4028", size = 65511, upload-time = "2026-03-09T13:15:13.311Z" }, - { url = "https://files.pythonhosted.org/packages/f8/8a/685b297052dd041dcebce8e8787b58923b6e78acc6115a0dc9189011c44b/kiwisolver-1.5.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e7c4c09a490dc4d4a7f8cbee56c606a320f9dc28cf92a7157a39d1ce7676a657", size = 1584858, upload-time = "2026-03-09T13:15:15.103Z" }, - { url = "https://files.pythonhosted.org/packages/9e/80/04865e3d4638ac5bddec28908916df4a3075b8c6cc101786a96803188b96/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a075bd7bd19c70cf67c8badfa36cf7c5d8de3c9ddb8420c51e10d9c50e94920", size = 1392539, upload-time = "2026-03-09T13:15:16.661Z" }, - { url = "https://files.pythonhosted.org/packages/ba/01/77a19cacc0893fa13fafa46d1bba06fb4dc2360b3292baf4b56d8e067b24/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bdd3e53429ff02aa319ba59dfe4ceeec345bf46cf180ec2cf6fd5b942e7975e9", size = 1405310, upload-time = "2026-03-09T13:15:18.229Z" }, - { url = "https://files.pythonhosted.org/packages/53/39/bcaf5d0cca50e604cfa9b4e3ae1d64b50ca1ae5b754122396084599ef903/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cdcb35dc9d807259c981a85531048ede628eabcffb3239adf3d17463518992d", size = 1456244, upload-time = "2026-03-09T13:15:20.444Z" }, - { url = "https://files.pythonhosted.org/packages/d0/7a/72c187abc6975f6978c3e39b7cf67aeb8b3c0a8f9790aa7fd412855e9e1f/kiwisolver-1.5.0-cp314-cp314t-manylinux_2_39_riscv64.whl", hash = "sha256:70d593af6a6ca332d1df73d519fddb5148edb15cd90d5f0155e3746a6d4fcc65", size = 1073154, upload-time = "2026-03-09T13:15:22.039Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ca/cf5b25783ebbd59143b4371ed0c8428a278abe68d6d0104b01865b1bbd0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:377815a8616074cabbf3f53354e1d040c35815a134e01d7614b7692e4bf8acfa", size = 2334377, upload-time = "2026-03-09T13:15:23.741Z" }, - { url = "https://files.pythonhosted.org/packages/4a/e5/b1f492adc516796e88751282276745340e2a72dcd0d36cf7173e0daf3210/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0255a027391d52944eae1dbb5d4cc5903f57092f3674e8e544cdd2622826b3f0", size = 2425288, upload-time = "2026-03-09T13:15:25.789Z" }, - { url = "https://files.pythonhosted.org/packages/e6/e5/9b21fbe91a61b8f409d74a26498706e97a48008bfcd1864373d32a6ba31c/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:012b1eb16e28718fa782b5e61dc6f2da1f0792ca73bd05d54de6cb9561665fc9", size = 2063158, upload-time = "2026-03-09T13:15:27.63Z" }, - { url = "https://files.pythonhosted.org/packages/b1/02/83f47986138310f95ea95531f851b2a62227c11cbc3e690ae1374fe49f0f/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e3aafb33aed7479377e5e9a82e9d4bf87063741fc99fc7ae48b0f16e32bdd6f", size = 2597260, upload-time = "2026-03-09T13:15:29.421Z" }, - { url = "https://files.pythonhosted.org/packages/07/18/43a5f24608d8c313dd189cf838c8e68d75b115567c6279de7796197cfb6a/kiwisolver-1.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7a116ae737f0000343218c4edf5bd45893bfeaff0993c0b215d7124c9f77646", size = 2394403, upload-time = "2026-03-09T13:15:31.517Z" }, - { url = "https://files.pythonhosted.org/packages/3b/b5/98222136d839b8afabcaa943b09bd05888c2d36355b7e448550211d1fca4/kiwisolver-1.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1dd9b0b119a350976a6d781e7278ec7aca0b201e1a9e2d23d9804afecb6ca681", size = 79687, upload-time = "2026-03-09T13:15:33.204Z" }, - { url = "https://files.pythonhosted.org/packages/99/a2/ca7dc962848040befed12732dff6acae7fb3c4f6fc4272b3f6c9a30b8713/kiwisolver-1.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:58f812017cd2985c21fbffb4864d59174d4903dd66fa23815e74bbc7a0e2dd57", size = 70032, upload-time = "2026-03-09T13:15:34.411Z" }, - { url = "https://files.pythonhosted.org/packages/1c/fa/2910df836372d8761bb6eff7d8bdcb1613b5c2e03f260efe7abe34d388a7/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_10_13_x86_64.whl", hash = "sha256:5ae8e62c147495b01a0f4765c878e9bfdf843412446a247e28df59936e99e797", size = 130262, upload-time = "2026-03-09T13:15:35.629Z" }, - { url = "https://files.pythonhosted.org/packages/0f/41/c5f71f9f00aabcc71fee8b7475e3f64747282580c2fe748961ba29b18385/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:f6764a4ccab3078db14a632420930f6186058750df066b8ea2a7106df91d3203", size = 138036, upload-time = "2026-03-09T13:15:36.894Z" }, - { url = "https://files.pythonhosted.org/packages/fa/06/7399a607f434119c6e1fdc8ec89a8d51ccccadf3341dee4ead6bd14caaf5/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c31c13da98624f957b0fb1b5bae5383b2333c2c3f6793d9825dd5ce79b525cb7", size = 194295, upload-time = "2026-03-09T13:15:38.22Z" }, - { url = "https://files.pythonhosted.org/packages/b5/91/53255615acd2a1eaca307ede3c90eb550bae9c94581f8c00081b6b1c8f44/kiwisolver-1.5.0-graalpy312-graalpy250_312_native-win_amd64.whl", hash = "sha256:1f1489f769582498610e015a8ef2d36f28f505ab3096d0e16b4858a9ec214f57", size = 75987, upload-time = "2026-03-09T13:15:39.65Z" }, - { url = "https://files.pythonhosted.org/packages/e9/eb/5fcbbbf9a0e2c3a35effb88831a483345326bbc3a030a3b5b69aee647f84/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ec4c85dc4b687c7f7f15f553ff26a98bfe8c58f5f7f0ac8905f0ba4c7be60232", size = 59532, upload-time = "2026-03-09T13:15:47.047Z" }, - { url = "https://files.pythonhosted.org/packages/c3/9b/e17104555bb4db148fd52327feea1e96be4b88e8e008b029002c281a21ab/kiwisolver-1.5.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:12e91c215a96e39f57989c8912ae761286ac5a9584d04030ceb3368a357f017a", size = 57420, upload-time = "2026-03-09T13:15:48.199Z" }, - { url = "https://files.pythonhosted.org/packages/48/44/2b5b95b7aa39fb2d8d9d956e0f3d5d45aef2ae1d942d4c3ffac2f9cfed1a/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be4a51a55833dc29ab5d7503e7bcb3b3af3402d266018137127450005cdfe737", size = 79892, upload-time = "2026-03-09T13:15:49.694Z" }, - { url = "https://files.pythonhosted.org/packages/52/7d/7157f9bba6b455cfb4632ed411e199fc8b8977642c2b12082e1bd9e6d173/kiwisolver-1.5.0-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daae526907e262de627d8f70058a0f64acc9e2641c164c99c8f594b34a799a16", size = 77603, upload-time = "2026-03-09T13:15:50.945Z" }, - { url = "https://files.pythonhosted.org/packages/0a/dd/8050c947d435c8d4bc94e3252f4d8bb8a76cfb424f043a8680be637a57f1/kiwisolver-1.5.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:59cd8683f575d96df5bb48f6add94afc055012c29e28124fcae2b63661b9efb1", size = 73558, upload-time = "2026-03-09T13:15:52.112Z" }, -] - -[[package]] -name = "matplotlib" -version = "3.11.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "contourpy" }, - { name = "cycler" }, - { name = "fonttools" }, - { name = "kiwisolver" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, - { name = "numpy", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, - { name = "packaging" }, - { name = "pillow" }, - { name = "pyparsing" }, - { name = "python-dateutil" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/49/64/f9a391af28f518b11ad45a8a712353c94a0aefce09d3703200e5c54b610a/matplotlib-3.11.1.tar.gz", hash = "sha256:69647db5746941c793d6e445a4cd349323ffb87d9cc958c2ad84a659b4832d30", size = 32612045, upload-time = "2026-07-18T03:39:46.63Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/d0/791aa183dd88491555cf7d4be0b52b0bcf6c3c2a2c22c815a2e819bf53e2/matplotlib-3.11.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b7cf158e7add54a8d51ac9b5a84abd6d4e13ed4951b4f25f1c5139f41c2addb2", size = 9440302, upload-time = "2026-07-18T03:38:03.844Z" }, - { url = "https://files.pythonhosted.org/packages/35/74/82bbdf683a301f4478384c8aaba6903631a2ca18294b2d7655c9a542bffb/matplotlib-3.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d2ace7273b9a5061a3b420918a16fae1f2dc5dfee1abcc13aba71b5d94b1820c", size = 9268549, upload-time = "2026-07-18T03:38:06.144Z" }, - { url = "https://files.pythonhosted.org/packages/f0/f0/9b4298911303f74e6d83e64a81d996c0616405ec95046fac7f17e4258b9e/matplotlib-3.11.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aee55e9041211bf84302ab55ec3965df18dd90ae19f8b58332a7feaf208bfe83", size = 10024922, upload-time = "2026-07-18T03:38:08.236Z" }, - { url = "https://files.pythonhosted.org/packages/84/6f/0bc3c3d05b021db44c14bc379a7c0df7d57302aa15380c16fd4e63fd6a9b/matplotlib-3.11.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96f4bdeea33a8d15a071dbfe6d119451b1d719c733ac666d65357082901a9099", size = 10832170, upload-time = "2026-07-18T03:38:10.276Z" }, - { url = "https://files.pythonhosted.org/packages/db/4d/e375f39acdb2af5a9342730618608e39790ec842e6f1b392863028781459/matplotlib-3.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b4c78ceb2f11bcac7389d305cda17aeb1f4586a857854ab5780bd3dd8dbfc407", size = 10916701, upload-time = "2026-07-18T03:38:12.512Z" }, - { url = "https://files.pythonhosted.org/packages/bc/be/fa26ed085b41298f64a8f9b7592c671bbf1acc8b0df124c1c5de96b859f8/matplotlib-3.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f33a781e12b1e53b278deb2f5373c2e55ec4f10727be3440c0cfb5cda9f944f", size = 9315331, upload-time = "2026-07-18T03:38:14.949Z" }, - { url = "https://files.pythonhosted.org/packages/b6/f3/eb5bdf3b6e191b200db298b08bbc1638b7f3c82cdc8680f9d88bf72559ae/matplotlib-3.11.1-cp311-cp311-win_arm64.whl", hash = "sha256:67e4c3cd578c65ebd81bdc09a1b6592ceafee6dfafe116dc85dfcb647b5bbb18", size = 9003475, upload-time = "2026-07-18T03:38:17.205Z" }, - { url = "https://files.pythonhosted.org/packages/f2/6c/7ef7ebcb2bd9739b2b66b18b076e077f44bb46fdbe28ca0506edb3c62c79/matplotlib-3.11.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e15ef41507f3d525f46154ac9e3ae785dacde9f20e593a25de8986267892ef74", size = 9453849, upload-time = "2026-07-18T03:38:19.593Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/6d0c312c8d9738e7d9677f09fe5c986b3239e651a7b73a2deb38b65e4a71/matplotlib-3.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21a67b961a6d597bca54fae826cd20695ba4a6e4d05424a08da6e13e3176fd6b", size = 9283113, upload-time = "2026-07-18T03:38:21.95Z" }, - { url = "https://files.pythonhosted.org/packages/c9/cf/b4ad2cc81b6672ea29ea04e64e350a9f9b493b0908ccd884c67eeff8f7b2/matplotlib-3.11.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ba8f811b8ddfac493734d6af0b2dff96919d0c28ca0d641858dab4262777c6ea", size = 10035615, upload-time = "2026-07-18T03:38:24.315Z" }, - { url = "https://files.pythonhosted.org/packages/88/90/4e10e033d9b66589d8ed98b84c95cdbb57033d57c1f41339d7393dbd2f2e/matplotlib-3.11.1-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c52f7ad20ef476806ed212380b1d54d20310c8b86bdc2c9a68b51f0024a44472", size = 10842559, upload-time = "2026-07-18T03:38:26.285Z" }, - { url = "https://files.pythonhosted.org/packages/88/eb/799612d0f8cd3e816a10fec59329fca52cd2353264df80378dfc541ae855/matplotlib-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b14eb22961fe865efb0e4ff167e333e428908b00115a8d800ccb65ee108e481", size = 10927532, upload-time = "2026-07-18T03:38:28.532Z" }, - { url = "https://files.pythonhosted.org/packages/88/89/56649bbaa2fd12e20f3be03dbcc135b0c8676d88bac17977599e3eb442a0/matplotlib-3.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:88a2a27dd9691ae448dfae4b26f59036be90c3c28757edd3553a29559d00859f", size = 9333886, upload-time = "2026-07-18T03:38:30.477Z" }, - { url = "https://files.pythonhosted.org/packages/c1/11/4d124efbbad677b7b7552f6f85a3bd432d4232f95400cea98fcd2ae36ef3/matplotlib-3.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:480194afceca4df2f137c2721227d3cba67121fbf4397b69cee7f83714b0a58a", size = 9007545, upload-time = "2026-07-18T03:38:32.833Z" }, - { url = "https://files.pythonhosted.org/packages/04/6c/4798363b7fb5644e309fe1fac30216e9146c9f70859d80d588c18caf5317/matplotlib-3.11.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6771b0cd7838c6a857a7209814158c0ad09bfef878db3033dd82d70ad101f191", size = 9454341, upload-time = "2026-07-18T03:38:35.001Z" }, - { url = "https://files.pythonhosted.org/packages/59/98/6acadbe7f98df19d274bc107ac58bb439fa75df82c33dc110d71a4a8501f/matplotlib-3.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2abdee5ffa2fe11b2d19f7a5c63b785fb7c28cc46c7bc1814156341d9d1a33e1", size = 9283627, upload-time = "2026-07-18T03:38:37.061Z" }, - { url = "https://files.pythonhosted.org/packages/24/ea/65cec46fe241390ccea1b1754207ee28eb71c5ab866bd5f22fe47e538fa4/matplotlib-3.11.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b0a19dcf73406d3746d25a5ed42d713604c9a3e024d129b102852b0d941cb9f3", size = 10035860, upload-time = "2026-07-18T03:38:39.663Z" }, - { url = "https://files.pythonhosted.org/packages/c7/10/63fdccccbabe002fb0960876baabc5e3f24d9c1bb4cfb25651457f74b3a0/matplotlib-3.11.1-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7389b77ed2ab0552f46d9a90b81b7b8e6dfcdc42adc36c37a0865799843e0e3e", size = 10843594, upload-time = "2026-07-18T03:38:42.144Z" }, - { url = "https://files.pythonhosted.org/packages/98/51/a1155945bff7b91381875022ac1522c5dfdac0d006be8e7df389b3134eae/matplotlib-3.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c90be0b73568da4f662afac580956a76e308437e641b4a45aa08925eeb67d95f", size = 10927962, upload-time = "2026-07-18T03:38:44.302Z" }, - { url = "https://files.pythonhosted.org/packages/0d/3a/3d5e1f42dc761bf53401a62a83ff93389b37de9d2c093b2a3aa49ac34f1b/matplotlib-3.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:68408341f2312836fbbdf6b3c78047f65b2d8752f5fd221c3e72d348f5b34f8b", size = 9334074, upload-time = "2026-07-18T03:38:46.616Z" }, - { url = "https://files.pythonhosted.org/packages/e2/db/3f5ea5a5b64060ef5e1ff60a19170423e41ce21b8497a6fe15a36e0b43e3/matplotlib-3.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c1f44890d435c1b4ef52f701ad5828cb450ea97bcc83918fda6be74965d6cd2", size = 9007662, upload-time = "2026-07-18T03:38:49.112Z" }, - { url = "https://files.pythonhosted.org/packages/98/6e/c7ae5e0531425b69c0826b00ebbc264c85cab853f1cd6e096c9983c2cdc1/matplotlib-3.11.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:5e510088c27a89d53580a752f959146893563e63c330e161d159b0fee652af6f", size = 9503790, upload-time = "2026-07-18T03:38:51.527Z" }, - { url = "https://files.pythonhosted.org/packages/92/79/15be162e0a2ed546939674e2e97d0e33ec2447d86d4d4e611fa295bb178c/matplotlib-3.11.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:1524e2bdd48a93557aa47ddcfe9c225dfdd57d5a01a5c49128c20f0632980ee1", size = 9336148, upload-time = "2026-07-18T03:38:53.564Z" }, - { url = "https://files.pythonhosted.org/packages/6a/7f/36ffe144fc4aacfe0e3ed2318f72b6755d1e73b041d619b4d393e60f5a66/matplotlib-3.11.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:11664c551345553db92e61cae6cf1376f138f8c47cafdf13b64b18f3e3e9e464", size = 10049244, upload-time = "2026-07-18T03:38:55.911Z" }, - { url = "https://files.pythonhosted.org/packages/ab/5f/55812d68c0a840d3a463638f48c00ab1fe338518ec49a640cb6473b444af/matplotlib-3.11.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e1f8922ba31959cf6a9dfb51be64b7f7bc582801a3957dc0c2f3afcd3537adf", size = 10860798, upload-time = "2026-07-18T03:38:58.282Z" }, - { url = "https://files.pythonhosted.org/packages/7a/64/cca444b4eb5e6c768c44fc5e1f0b5211f20ca2b282778051996e996a2bdf/matplotlib-3.11.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83235693abde86e5e0129998f80ee39fc7f58e6d56a88fafb28a9278833e9d5f", size = 10943282, upload-time = "2026-07-18T03:39:00.465Z" }, - { url = "https://files.pythonhosted.org/packages/e5/0f/a49c329d394f2e9ef38506982107e8b04ecf94dd41a9d8423ff82cc737c7/matplotlib-3.11.1-cp313-cp313t-win_amd64.whl", hash = "sha256:9a076f4fc5cdc43fdf510f5981418d25c2db4973418d9f22d8bb3dc8045ada78", size = 9383532, upload-time = "2026-07-18T03:39:02.468Z" }, - { url = "https://files.pythonhosted.org/packages/e4/50/103e86afb806d8f64d04ede14e4cfc09dbfc25f512421ff85fdd6ebd59cf/matplotlib-3.11.1-cp313-cp313t-win_arm64.whl", hash = "sha256:216fbb93a74add02ddb4cb38ef5348f59ac00b3e84567eaf16598772d40e150a", size = 9059665, upload-time = "2026-07-18T03:39:04.607Z" }, - { url = "https://files.pythonhosted.org/packages/35/04/3079499fa8cb661ea66d13d6439d5a3ae6710a7afd5c7f72e08914f275f8/matplotlib-3.11.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:30c492d4ba9448595b6fd8708c6725963f8148e25c0d8842948da5b05f0ee8d3", size = 9456022, upload-time = "2026-07-18T03:39:07.041Z" }, - { url = "https://files.pythonhosted.org/packages/53/a2/69acfe84ec1f32930e801a5782a07fc5c79c8c6599a507b806d859d5da8e/matplotlib-3.11.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ac104be2768ffdd8655db9e71b768cbb45f2b9aa7b450cf1595e8f65d3822319", size = 9285475, upload-time = "2026-07-18T03:39:09.562Z" }, - { url = "https://files.pythonhosted.org/packages/d3/b3/31b15a2ca56d4ddd6aaa1c884c2f51cf9a61cfaf5ca6f6fbd6343d38e6df/matplotlib-3.11.1-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6be943cb68bc6660ead58c55b3aa6366cba2ef7feb06460fbcce32360376f19f", size = 10847102, upload-time = "2026-07-18T03:39:11.532Z" }, - { url = "https://files.pythonhosted.org/packages/64/0d/a17e966e620545c1548125af0b29ac812dd17b197a18a7462ac12fa859ee/matplotlib-3.11.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5af0dcda57d471440a7b5b623e70e0a61003518443d9098f211a96ecfbbc25be", size = 11131087, upload-time = "2026-07-18T03:39:13.764Z" }, - { url = "https://files.pythonhosted.org/packages/97/c5/5e100efdd67abb7de20befaa333612ef9bfc63417fb71398f904f25d083c/matplotlib-3.11.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3d3fd84082b1afbd9398466c81309e20045be20d48fe0fb18c43504d164cbbb2", size = 10929036, upload-time = "2026-07-18T03:39:16.888Z" }, - { url = "https://files.pythonhosted.org/packages/ce/04/d719a0a36930ecc8dfc801ff340f9dcfc4223f8ca5d39d06b4020032fff8/matplotlib-3.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:9601a1e90be21e4884c53b4f3dc3ee0544654946f9975258d691f1c2e2f119c6", size = 9489571, upload-time = "2026-07-18T03:39:19.449Z" }, - { url = "https://files.pythonhosted.org/packages/48/65/facabdc2f1f6caba7e856db64dfedddca25f7608df07d96a1c8fd114fd3b/matplotlib-3.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:ae30c6109848ac0f9fa36c5d6270938487614c47ba31860bd5361266dabc5685", size = 9164486, upload-time = "2026-07-18T03:39:21.424Z" }, - { url = "https://files.pythonhosted.org/packages/88/dd/18da6cd01cf96354534f98c468a25380c68ce582a2c9dd0cae12b04af4f2/matplotlib-3.11.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:dadfe80797174e2984aae3be0b77594a3c72d2c0a40fbd4a0de48d2728caf3ae", size = 9504876, upload-time = "2026-07-18T03:39:23.633Z" }, - { url = "https://files.pythonhosted.org/packages/79/b0/f0b63555a18b79d038c81fd6126f35fc4dfce0eaff48d96103348c7cf935/matplotlib-3.11.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:89b193b255f4f6f7948dbcee3691f4f341ab05d9a8874a67b45ddb4182922eda", size = 9336120, upload-time = "2026-07-18T03:39:25.797Z" }, - { url = "https://files.pythonhosted.org/packages/c6/dd/f210ec7c4a6f198d5567237048a93d0811fb5a1f1691f13320e592f95b41/matplotlib-3.11.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:191163532cdefcb1571ca38a6d7e6474baccde64495783e6ba47aa07ec4b9bbb", size = 10858033, upload-time = "2026-07-18T03:39:27.999Z" }, - { url = "https://files.pythonhosted.org/packages/ec/d2/d6d5324507c5fbb316db48e258c09c2807f3de03d9af47017e120070926f/matplotlib-3.11.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9fdf1c818ab05d0e74002091ddaf414478a3a449ec9d51c8976d45be7e3a01e2", size = 11141827, upload-time = "2026-07-18T03:39:30.092Z" }, - { url = "https://files.pythonhosted.org/packages/0f/68/3c22e9320bdce2c4d2f1320643ef706db7a24cb7420eea28b97a2d67f5a8/matplotlib-3.11.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b937b9dba5f5f6c1e31c47abe2186c865c0914fd18f2ce0dfc39c9adcef5951d", size = 10943061, upload-time = "2026-07-18T03:39:32.356Z" }, - { url = "https://files.pythonhosted.org/packages/f6/4a/907ed190ee81a9df581e0ed5456134fc0f7cb55ffcfda2f9e54ca900761c/matplotlib-3.11.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f2912f647f3fbe1ccf085f91e213936f9101bead81a5e670565b1f1b3712f4fb", size = 9540074, upload-time = "2026-07-18T03:39:34.789Z" }, - { url = "https://files.pythonhosted.org/packages/23/d4/97c19b77e0a6e3b48581185bb65088f431cd20186076cc0f650a1757ea46/matplotlib-3.11.1-cp314-cp314t-win_arm64.whl", hash = "sha256:54d47b8ae8b579633a3902ca5b4ad6c1e132a5626d64447b2e22a66394e79987", size = 9213472, upload-time = "2026-07-18T03:39:37.141Z" }, - { url = "https://files.pythonhosted.org/packages/ee/38/ceb1d637c4db6d06141f3739e93af3321e7caaabe69b57ae48ffe3ee95b1/matplotlib-3.11.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:427258425f9a3fc4ed79a91f9e9b9aaf5a82cb6571e85dc14063cc6fbb993741", size = 9438045, upload-time = "2026-07-18T03:39:39.491Z" }, - { url = "https://files.pythonhosted.org/packages/89/25/72ad8b58602d3a6ef1dfc4b65ecd01634ab65a2bdf494c9fe0e966dbf081/matplotlib-3.11.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:1ac697e591c11b6ad04679a73c2d2f9980fe9d9f0311fb414a2e329706343dfb", size = 9266127, upload-time = "2026-07-18T03:39:41.597Z" }, - { url = "https://files.pythonhosted.org/packages/8a/6d/69552382fcc8e93d1f2763ef2665980a900a48b7f3a4c57ed290726d1cbc/matplotlib-3.11.1-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e4b9ac2f1f607ecda2af90a5232beee2af7582fce1cc30c4b6a1b012dc21ee99", size = 10019439, upload-time = "2026-07-18T03:39:43.78Z" }, -] - -[[package]] -name = "numpy" -version = "2.4.6" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.12'", -] -sdist = { url = "https://files.pythonhosted.org/packages/d0/ad/fed0499ce6a338d2a03ebae59cd15093910c8875328855781952abf6c2fe/numpy-2.4.6.tar.gz", hash = "sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda", size = 20735807, upload-time = "2026-05-18T23:37:14.07Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/49/ec46835a70be8fa6446c495126ac84fdb28cb2558e1620ffb87a10c8b64c/numpy-2.4.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4", size = 16969194, upload-time = "2026-05-18T23:33:13.503Z" }, - { url = "https://files.pythonhosted.org/packages/0e/0d/f5957185c0ee2f3e12f78715aa9e3b353fd83633316c8532b38faa37e3f6/numpy-2.4.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d", size = 14964111, upload-time = "2026-05-18T23:33:17.795Z" }, - { url = "https://files.pythonhosted.org/packages/ad/40/40a40ee0ddf7ceb782c49af278894b686e586d65d8c1889c8b5da01a3d7d/numpy-2.4.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8", size = 5469159, upload-time = "2026-05-18T23:33:20.654Z" }, - { url = "https://files.pythonhosted.org/packages/63/13/f9a8046535cb21deae82f8d03de9617e08882d274fad2539630761888228/numpy-2.4.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538", size = 6798936, upload-time = "2026-05-18T23:33:22.987Z" }, - { url = "https://files.pythonhosted.org/packages/33/a8/6fa8c1a345a8c85dbb21932c447bee07c30a2c2a3f31e369c0a84b300147/numpy-2.4.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47", size = 15966692, upload-time = "2026-05-18T23:33:26.62Z" }, - { url = "https://files.pythonhosted.org/packages/02/03/74fe2a4cb3817d94d86402f2506554130a2f01414e299b5a843e5a8a957f/numpy-2.4.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93", size = 16918164, upload-time = "2026-05-18T23:33:29.955Z" }, - { url = "https://files.pythonhosted.org/packages/c5/80/3615be3313f7e7696609bc194b9f0101da809df79e859bdb84e0cd043f46/numpy-2.4.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8", size = 17322877, upload-time = "2026-05-18T23:33:34.724Z" }, - { url = "https://files.pythonhosted.org/packages/ca/ac/a691e0fe2675e370d0e08ff905adc49a1c8830e8cae03efe4477e92cd55d/numpy-2.4.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6", size = 18651487, upload-time = "2026-05-18T23:33:38.217Z" }, - { url = "https://files.pythonhosted.org/packages/15/a7/9bc1cd626d7bf6869bfedf27b91b6ab5dd607758bf8e959d6fa80c6a59cb/numpy-2.4.6-cp311-cp311-win32.whl", hash = "sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8", size = 6233945, upload-time = "2026-05-18T23:33:41.331Z" }, - { url = "https://files.pythonhosted.org/packages/c5/31/7fc6239c12bce7e931463251cca4426c465e1876ba3cc785402ef4dd8f4e/numpy-2.4.6-cp311-cp311-win_amd64.whl", hash = "sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147", size = 12608406, upload-time = "2026-05-18T23:33:44.131Z" }, - { url = "https://files.pythonhosted.org/packages/27/83/140f85a466595a16382996a1bf06b2b54bcd597488921b0c9daaeeda72af/numpy-2.4.6-cp311-cp311-win_arm64.whl", hash = "sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577", size = 10479528, upload-time = "2026-05-18T23:33:50.725Z" }, - { url = "https://files.pythonhosted.org/packages/95/2a/3d7b5ac8aac24feaf9ad7ed58f45b0bbc06d37e4338ae84c9f2298b570f9/numpy-2.4.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1", size = 16689119, upload-time = "2026-05-18T23:33:54.065Z" }, - { url = "https://files.pythonhosted.org/packages/ea/12/92c4c131527599e8288d6918e888d88726f84d805d784b771f32408aeaef/numpy-2.4.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb", size = 14699246, upload-time = "2026-05-18T23:33:57.621Z" }, - { url = "https://files.pythonhosted.org/packages/ad/fe/c0a6b7b2ca128a8fb228575147073b660656734b8ebe4d76c8fd748dcc79/numpy-2.4.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41", size = 5204410, upload-time = "2026-05-18T23:34:00.302Z" }, - { url = "https://files.pythonhosted.org/packages/f3/d4/9770d14ba719432bb90a421bfd443872ed0f70f7264b64bec12ea363d5fd/numpy-2.4.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698", size = 6551240, upload-time = "2026-05-18T23:34:02.852Z" }, - { url = "https://files.pythonhosted.org/packages/c9/c6/50a46a6205feba2343f1d6d17438107c5dc491ed1c736e6ea68689fd906b/numpy-2.4.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f", size = 15671012, upload-time = "2026-05-18T23:34:05.485Z" }, - { url = "https://files.pythonhosted.org/packages/99/60/14115e6364fa676c5397c2ad3004e527e9aa487abf5d0706ec81bbd08529/numpy-2.4.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853", size = 16645538, upload-time = "2026-05-18T23:34:09.265Z" }, - { url = "https://files.pythonhosted.org/packages/ae/c5/693cbe59e57db94d2231fa519ca3978dc9e19da5a8f088588f5c6e947ff2/numpy-2.4.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a", size = 17020706, upload-time = "2026-05-18T23:34:13.053Z" }, - { url = "https://files.pythonhosted.org/packages/ef/fc/85b7c4eff9b4966ade25c2273cf7e7012e92366c032058653934b37de044/numpy-2.4.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2", size = 18368541, upload-time = "2026-05-18T23:34:17.024Z" }, - { url = "https://files.pythonhosted.org/packages/f6/81/e1b27545deedce7f4a0b348618c6b62d74e36a4dc9ccd42f3eb2f85eee32/numpy-2.4.6-cp312-cp312-win32.whl", hash = "sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45", size = 5962825, upload-time = "2026-05-18T23:34:20.3Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ca/feab00bd44aa5fe1ad2c18f08b4d3bb92e26484b0b1d1443897809ed528c/numpy-2.4.6-cp312-cp312-win_amd64.whl", hash = "sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751", size = 12321687, upload-time = "2026-05-18T23:34:23.095Z" }, - { url = "https://files.pythonhosted.org/packages/63/cf/5a6d34850a39d1093558564f77ee8e8e0bee5061151b8f05a55711001ec7/numpy-2.4.6-cp312-cp312-win_arm64.whl", hash = "sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8", size = 10221482, upload-time = "2026-05-18T23:34:25.876Z" }, - { url = "https://files.pythonhosted.org/packages/fb/82/bdab26d7438c6791ca31b7c024ca37c1eab8b726ba236129005cd4a06e45/numpy-2.4.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0", size = 16684648, upload-time = "2026-05-18T23:34:29.41Z" }, - { url = "https://files.pythonhosted.org/packages/1b/30/a80189bcc7f5e4258b3fbc3968d909d1756f54d023299ecc39ad6fdb9ef8/numpy-2.4.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb", size = 14693902, upload-time = "2026-05-18T23:34:33.013Z" }, - { url = "https://files.pythonhosted.org/packages/97/12/70b5d0d7c15e1ebb8a6a84a8caa1d19e181d84fb58bb6d70aca29099dec1/numpy-2.4.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f", size = 5198992, upload-time = "2026-05-18T23:34:36.132Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8c/ebd2a8f8a83541f8d38cc5667e8c2b69cecfd30da6e45693e8158857d44b/numpy-2.4.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3", size = 6546944, upload-time = "2026-05-18T23:34:38.484Z" }, - { url = "https://files.pythonhosted.org/packages/bb/c5/7b863a97a91671a0338f4253bd3b5a3d3852f0692dae91711c9f4a10e787/numpy-2.4.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b", size = 15669392, upload-time = "2026-05-18T23:34:41.257Z" }, - { url = "https://files.pythonhosted.org/packages/a5/9d/3584b9984ca4c047aea75214ce1a4c4c73d849bd71b604264b7f5653f8a8/numpy-2.4.6-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089", size = 16633220, upload-time = "2026-05-18T23:34:45.075Z" }, - { url = "https://files.pythonhosted.org/packages/05/ae/7c67fba23bd98caec7c99261f3a16072ade14813486b0282cb29846de832/numpy-2.4.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a", size = 17020800, upload-time = "2026-05-18T23:34:49.065Z" }, - { url = "https://files.pythonhosted.org/packages/d9/5d/3b6725cb31d983c5e66916f5d36f6d7e5521129e4c4404d64f918292a5b6/numpy-2.4.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605", size = 18357600, upload-time = "2026-05-18T23:34:52.709Z" }, - { url = "https://files.pythonhosted.org/packages/f7/da/2ccc6c2fe8898dee01d90c75c5f5f914a23daf99e3e0f59516a08760c8b5/numpy-2.4.6-cp313-cp313-win32.whl", hash = "sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91", size = 5961134, upload-time = "2026-05-18T23:34:55.618Z" }, - { url = "https://files.pythonhosted.org/packages/b5/cd/9cc4dc876fb065d5c220aae4d5e14826b2715331bb7618ce1fb07a679d99/numpy-2.4.6-cp313-cp313-win_amd64.whl", hash = "sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359", size = 12318598, upload-time = "2026-05-18T23:34:58.928Z" }, - { url = "https://files.pythonhosted.org/packages/39/1e/c0bcba1f8694116485fe28fd1be698c278fcda4141c5b0e53a2aed8b12a8/numpy-2.4.6-cp313-cp313-win_arm64.whl", hash = "sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778", size = 10222272, upload-time = "2026-05-18T23:35:02.167Z" }, - { url = "https://files.pythonhosted.org/packages/63/6d/cc5619247c8f4204e507f5883528372e4ac4bb189e579fb859a12e480b1f/numpy-2.4.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1", size = 14821197, upload-time = "2026-05-18T23:35:05.468Z" }, - { url = "https://files.pythonhosted.org/packages/00/58/f1c39161c87d9e9bed660f1ed4bafc0e403d5ec9650b6dd77aead07d489b/numpy-2.4.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe", size = 5326287, upload-time = "2026-05-18T23:35:08.693Z" }, - { url = "https://files.pythonhosted.org/packages/af/57/3917ab0fd97f271a8694513581b8a36c655f111c446852c302f04ccdb6fc/numpy-2.4.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997", size = 6646763, upload-time = "2026-05-18T23:35:11.459Z" }, - { url = "https://files.pythonhosted.org/packages/eb/0f/037e64c494b67581ae18193d770adef354c41f3f2c8ebf865602d949bf8f/numpy-2.4.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20", size = 15728070, upload-time = "2026-05-18T23:35:14.79Z" }, - { url = "https://files.pythonhosted.org/packages/21/a6/5d2bae9c9542eb4df16dc9c46dc79c186e9bad53805dfa5399a6023c6db0/numpy-2.4.6-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d", size = 16681752, upload-time = "2026-05-18T23:35:18.836Z" }, - { url = "https://files.pythonhosted.org/packages/92/14/23d1dfb410ae362cd59ce53e936b1513d545eb40db3949ced632e19a459e/numpy-2.4.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67", size = 17086024, upload-time = "2026-05-18T23:35:22.52Z" }, - { url = "https://files.pythonhosted.org/packages/4b/6e/23595a2c642cdf3bc567877064bdd7f91c8b0038a4453cf2daf7248eafe9/numpy-2.4.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd", size = 18403398, upload-time = "2026-05-18T23:35:26.398Z" }, - { url = "https://files.pythonhosted.org/packages/8a/90/0ac3bc947217e66dec77e7cbc6a1979d1af70b6461b82f620d3bccd5e4c8/numpy-2.4.6-cp313-cp313t-win32.whl", hash = "sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab", size = 6084971, upload-time = "2026-05-18T23:35:29.387Z" }, - { url = "https://files.pythonhosted.org/packages/77/71/5673e351671a1d2bd6063b91b44f70c0affea7d1516fa7a6572941ba4aa1/numpy-2.4.6-cp313-cp313t-win_amd64.whl", hash = "sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75", size = 12458532, upload-time = "2026-05-18T23:35:32.175Z" }, - { url = "https://files.pythonhosted.org/packages/3f/88/19d3503c5046e688f049274b27a3ef3d771152fa80d3ba3d01a3dff61abe/numpy-2.4.6-cp313-cp313t-win_arm64.whl", hash = "sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd", size = 10291881, upload-time = "2026-05-18T23:35:35.465Z" }, - { url = "https://files.pythonhosted.org/packages/f8/91/3ab2044d05fd16d343c5ac2e69b127f1b2854040dd20b193257c78028bd3/numpy-2.4.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079", size = 16683458, upload-time = "2026-05-18T23:35:38.353Z" }, - { url = "https://files.pythonhosted.org/packages/8e/62/764ce66fa4147ae6d73071a3abf804ffe606f174618697c571acdf26a7c9/numpy-2.4.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7", size = 14704559, upload-time = "2026-05-18T23:35:42.14Z" }, - { url = "https://files.pythonhosted.org/packages/60/61/23f27c172f022e04025b7dc2367f4d63c1a398120607ec896228649a6f48/numpy-2.4.6-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5", size = 5209716, upload-time = "2026-05-18T23:35:45.377Z" }, - { url = "https://files.pythonhosted.org/packages/03/71/21cf70dc6ea3e3acb95fc53a265b2fc248b981f0194ceb5b475271b8809d/numpy-2.4.6-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096", size = 6543947, upload-time = "2026-05-18T23:35:47.926Z" }, - { url = "https://files.pythonhosted.org/packages/d5/91/64288395ee1799bd2e0b04a305dce9666da90c961e1f3fe982a05ee1c036/numpy-2.4.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b", size = 15685197, upload-time = "2026-05-18T23:35:50.863Z" }, - { url = "https://files.pythonhosted.org/packages/f3/eb/ebffaa97dc55502df69584a8f0dcf07f69a3e0b3e2323670a2722db9aa39/numpy-2.4.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8", size = 16638245, upload-time = "2026-05-18T23:35:54.752Z" }, - { url = "https://files.pythonhosted.org/packages/b8/0b/54f9da33128d7e350fab89c7455902eeae70349ee52bddb448dc4a576f45/numpy-2.4.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402", size = 17036587, upload-time = "2026-05-18T23:35:58.355Z" }, - { url = "https://files.pythonhosted.org/packages/b6/f0/fdebc1052db1cc37c64beb22072d67cd6d1c71adca1299f53dec2b5e20d3/numpy-2.4.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb", size = 18363226, upload-time = "2026-05-18T23:36:02.845Z" }, - { url = "https://files.pythonhosted.org/packages/aa/b4/298628d98c72b57e57f7165ae6a481a1deaf6f3c28262a6e4c739c275930/numpy-2.4.6-cp314-cp314-win32.whl", hash = "sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1", size = 6010196, upload-time = "2026-05-18T23:36:05.92Z" }, - { url = "https://files.pythonhosted.org/packages/df/ac/46de6dda46478f7942f839e094970be2d4a861e005c4b3bf07c92e291a09/numpy-2.4.6-cp314-cp314-win_amd64.whl", hash = "sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261", size = 12450334, upload-time = "2026-05-18T23:36:09.107Z" }, - { url = "https://files.pythonhosted.org/packages/78/92/b8b798ac784102c0da830d2257d59358e3d3d90d1e2b3f2575dad976c5cf/numpy-2.4.6-cp314-cp314-win_arm64.whl", hash = "sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6", size = 10495678, upload-time = "2026-05-18T23:36:12.766Z" }, - { url = "https://files.pythonhosted.org/packages/30/34/ec28d1aa8115971537c01469ab2011ee96827930f0a124de1000cc2a7ed7/numpy-2.4.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a", size = 14823672, upload-time = "2026-05-18T23:36:16.473Z" }, - { url = "https://files.pythonhosted.org/packages/16/bd/f6d1fede4e54e8042a7ff97bb495510f3c220f94bcd9e8b228e87c92cc0d/numpy-2.4.6-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e", size = 5328731, upload-time = "2026-05-18T23:36:19.767Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f0/e105b9e2fd728a9910103884decd6951d9dd73896b914a98d9a231de02ee/numpy-2.4.6-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e", size = 6649805, upload-time = "2026-05-18T23:36:22.266Z" }, - { url = "https://files.pythonhosted.org/packages/82/dd/1206a7ca6ab15e3f02069707ca96222e202af681bb73756da7527f3cb837/numpy-2.4.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43", size = 15730496, upload-time = "2026-05-18T23:36:25.713Z" }, - { url = "https://files.pythonhosted.org/packages/51/e7/38d3ea825dcab85a591734decb2f6c67caa7c8367d374df1a1c3842f9b07/numpy-2.4.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e", size = 16679616, upload-time = "2026-05-18T23:36:29.652Z" }, - { url = "https://files.pythonhosted.org/packages/93/b7/caabfdf53edf663e0b4eb74d7d405d83baef09eb5e83bcd32d601d72b93e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895", size = 17085145, upload-time = "2026-05-18T23:36:33.449Z" }, - { url = "https://files.pythonhosted.org/packages/f9/45/68d7c33a6bcf3e5aa3bdbd57a367e6f615286dfd6482f97e8ffeb734306e/numpy-2.4.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4", size = 18403813, upload-time = "2026-05-18T23:36:37.369Z" }, - { url = "https://files.pythonhosted.org/packages/9c/50/0753655aa844c99cd9e018aacf76f130f1bd81d881bb74bc0aef5d73a8ba/numpy-2.4.6-cp314-cp314t-win32.whl", hash = "sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063", size = 6156982, upload-time = "2026-05-18T23:36:40.817Z" }, - { url = "https://files.pythonhosted.org/packages/b2/d4/7c67becf668f973cb490cec3e98dfd799d866f9c989a54d355672cfa0db6/numpy-2.4.6-cp314-cp314t-win_amd64.whl", hash = "sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627", size = 12638908, upload-time = "2026-05-18T23:36:43.996Z" }, - { url = "https://files.pythonhosted.org/packages/43/bb/e1c71a4295b1b1d1393d50dbb4f2a36283c6859d9d3892e84f00ec5a91d5/numpy-2.4.6-cp314-cp314t-win_arm64.whl", hash = "sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66", size = 10565867, upload-time = "2026-05-18T23:36:47.114Z" }, - { url = "https://files.pythonhosted.org/packages/de/12/b422cc84439adc0d00de605bf4a308890ae5c26f2c71fbd73e5d08fbb0dd/numpy-2.4.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662", size = 16847511, upload-time = "2026-05-18T23:36:50.673Z" }, - { url = "https://files.pythonhosted.org/packages/44/53/f481bef68011740f8849418d82db07230e825013f31f4eef5ba5b805316a/numpy-2.4.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7", size = 14889064, upload-time = "2026-05-18T23:36:53.879Z" }, - { url = "https://files.pythonhosted.org/packages/7f/57/42ed575c10ced8af951d426bc4e1f8aff16fd851db33f067036215a7f860/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f", size = 5394157, upload-time = "2026-05-18T23:36:57.194Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ef/f66cc724fcc36c1e364c67f51ae9146090b8b584f27d58b97fdae3edd737/numpy-2.4.6-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c", size = 6708728, upload-time = "2026-05-18T23:36:59.575Z" }, - { url = "https://files.pythonhosted.org/packages/1a/9c/c531f2293b91265d8b48e9b329f54fdd7ffae73cb4134ea10cca4237e9cc/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0", size = 15798374, upload-time = "2026-05-18T23:37:02.674Z" }, - { url = "https://files.pythonhosted.org/packages/1a/b0/413077f6b1153ed3cba361401c6783bbad6114804a000cc22eb71c13e190/numpy-2.4.6-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02", size = 16747286, upload-time = "2026-05-18T23:37:06.327Z" }, - { url = "https://files.pythonhosted.org/packages/15/ce/e5ec180bc41812edcd8daeb8639d205622c0e8c02259d8ab25a0201b3c2a/numpy-2.4.6-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73", size = 12504263, upload-time = "2026-05-18T23:37:09.715Z" }, -] - -[[package]] -name = "numpy" -version = "2.5.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.12'", -] -sdist = { url = "https://files.pythonhosted.org/packages/22/fd/89965aa4ac08c74998539fcbf24fa3540f3e15237fbeb6bcf9c908f4aade/numpy-2.5.1.tar.gz", hash = "sha256:a48a113e6afea91f5608793bafa7ef2ad481fefbda87ec5069f483de61cb9fa3", size = 20755553, upload-time = "2026-07-04T17:08:00.933Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/62/7b/14687aa674250e5e546f616f486b0d56d3631cd5b2415739141ce40bdcea/numpy-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c889b56fe48b1018f764b0eec8df59ab654e9148aa91faa12596043500de277", size = 16801574, upload-time = "2026-07-04T17:06:12.423Z" }, - { url = "https://files.pythonhosted.org/packages/e1/19/cc5bb2a3f2913d27d6dbb2c78d25921fabaedc6741d4a5a615a11f3c5bf3/numpy-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab451b59c5643c570974c43aef780703ef1d3b4965d2be07afd530615a9358d1", size = 11772250, upload-time = "2026-07-04T17:06:15.726Z" }, - { url = "https://files.pythonhosted.org/packages/42/77/fdf34a71dd30f54979b18603bee915e0aaf825b07afe79acd60b04b691e2/numpy-2.5.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:78798bd5b9ad744056af8efa90e3b9ddaa53272a0848a483084a1cc0a13b2dc0", size = 5331516, upload-time = "2026-07-04T17:06:17.913Z" }, - { url = "https://files.pythonhosted.org/packages/ce/e2/eb7efa015b4cce41e2517bf182a7fce0d7d5b9d9ed76a29bfa0f4fe4505c/numpy-2.5.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2ae0ca40bcb22d6ba59c1dfd5446f49940b0f2d821fde133f10dda11f816b84e", size = 6664863, upload-time = "2026-07-04T17:06:20.02Z" }, - { url = "https://files.pythonhosted.org/packages/a9/4b/a2b32dd94ee9ffbeecb28152240042a3949db33b1c834d44090b80e1b3b8/numpy-2.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61ac47e772e6b8ea489e1d2f441a34c5c3ac17327e7ce294cbdf535795ad4e75", size = 15167977, upload-time = "2026-07-04T17:06:21.621Z" }, - { url = "https://files.pythonhosted.org/packages/b8/a9/6e73d68500f80773f65f0654ea932019d6694329a0eb0ed0533de38df376/numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59fda5e192b570217ec2580c96f00e9a7e12ef6866a900eb089b62c1a32545ca", size = 16672469, upload-time = "2026-07-04T17:06:24.064Z" }, - { url = "https://files.pythonhosted.org/packages/24/7d/ad3e59015135f5261c95fd4cafeff159c955febd83a99a1d9250c4233815/numpy-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f7119ebff1a9829e9f431a4f9d28e703023bb6b9fe7c8f724467dbfc27c94ab3", size = 16527531, upload-time = "2026-07-04T17:06:26.69Z" }, - { url = "https://files.pythonhosted.org/packages/83/d0/a39b2fbcde9cb17a1dac678f254b33a6336298af9df338824c685425d5e8/numpy-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e824c2acf8862052246be5a44c15da1777940c60d010dd2aab897824d9c430f9", size = 18431940, upload-time = "2026-07-04T17:06:29.521Z" }, - { url = "https://files.pythonhosted.org/packages/04/12/cff070947791c1ed425ff76413189adbdc2fbe215eba7ce7fa454a03c7f8/numpy-2.5.1-cp312-cp312-win32.whl", hash = "sha256:08d60c810432eb83360958dea0999ac4cfb94531ea8efcbf0b7f277c2068aeb2", size = 6066764, upload-time = "2026-07-04T17:06:32.571Z" }, - { url = "https://files.pythonhosted.org/packages/65/66/53f31807a48a750f9d748da273bc3fcedd12b27ff1f3e373bfec55ef2dc0/numpy-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7d60026c0bdb1380e83bfa7a0419c4577ee4b9a08880afcb6dadeb74c649fa2", size = 12430966, upload-time = "2026-07-04T17:06:34.926Z" }, - { url = "https://files.pythonhosted.org/packages/2b/2a/d1a88066b1c14186f5d3c0d18c94f17b064511982bab0578d49ee9d43c29/numpy-2.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:17a25e09640602e10bc8de0e6fa2b3fd68eedd84ba6d7842dc8f32f9ab87bd0b", size = 10350488, upload-time = "2026-07-04T17:06:37.785Z" }, - { url = "https://files.pythonhosted.org/packages/eb/07/ec2a3f0c91761581d4b7104a740791800025983f9a4dc4e73f91a99aeac4/numpy-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0bfebd8695f9863592fe744be833a258120b14a9f39da255e8aa8fade2c0ddd1", size = 16796419, upload-time = "2026-07-04T17:06:40.37Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ab/ddb499fc4f8780354395face5b65c7fd107bcd6e1d667a5f07d046956f6f/numpy-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30b44a6b53a7ae63c54c089a8726e5563ed302716c5b7ccc85afade40b0e7ff6", size = 11765832, upload-time = "2026-07-04T17:06:42.768Z" }, - { url = "https://files.pythonhosted.org/packages/88/b3/3c28c558a09fc72100c646dac6d2fce8e834c471b0edca01a29996706117/numpy-2.5.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6165343f81b56ef8f514f396989e529b61d9dc709b99421b07e9f3e698e2287d", size = 5325143, upload-time = "2026-07-04T17:06:45.466Z" }, - { url = "https://files.pythonhosted.org/packages/5e/0e/ce19b985bb15c596f4f05954e76cccc77c845083b3b8f938a6c68e523128/numpy-2.5.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4939237038ada79308dda3204ac6462df056b5672b2e25db1149cf873668b3e1", size = 6659749, upload-time = "2026-07-04T17:06:47.288Z" }, - { url = "https://files.pythonhosted.org/packages/2e/20/1ee6614d64332a1bba6411f38e68cb79eec1b2459e20a623777c5c5492a2/numpy-2.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c6759f538fb912fc46de0a6b1758ccf7b57bc7c7ebebc23974fdac3de8db0cd", size = 15164716, upload-time = "2026-07-04T17:06:49.494Z" }, - { url = "https://files.pythonhosted.org/packages/ed/a7/2bcd3fdbb87804755c35b729bf8709d62025c5f4cfd7d5b2415997097515/numpy-2.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726558e8db4a5bf7929a70ae50f63abda4daf0efe810e3bfbab95976f75fc1a", size = 16661440, upload-time = "2026-07-04T17:06:52.061Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d7/a41e3310c886fe457d36e670bbf24fae411aca8a7b6ad92a32afd924077c/numpy-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3935f3b419b244a02732676fa5317a9193cc596a4c0646db07e5b421229ac9f7", size = 16526305, upload-time = "2026-07-04T17:06:54.605Z" }, - { url = "https://files.pythonhosted.org/packages/53/75/4333a9a707c1edd3a4e1a0c58eca52c0f31e55089fa80db02b5565b24df7/numpy-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc932a65ded7ce9013d120845a2514dcccb1a67bfc8deb8d37633762951904a6", size = 18423008, upload-time = "2026-07-04T17:06:57.54Z" }, - { url = "https://files.pythonhosted.org/packages/ee/90/e314a32b1c11a2ffe818ddad3a57b50b4b6e1b6c487192eb50cdef0415d0/numpy-2.5.1-cp313-cp313-win32.whl", hash = "sha256:4b4ff1608417eb7a59da7b967bbb798cacfe071d2caf526a24281cd562072ed9", size = 6063885, upload-time = "2026-07-04T17:07:00.14Z" }, - { url = "https://files.pythonhosted.org/packages/10/70/800b3fca480af32df9e8ea9f3d4a0c8feb4b32d7f195d174eabbda4829ad/numpy-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:6c3fe51bc6a16453d452997053454f309e8e0ed7b42d6b361ce4ac8c32913d74", size = 12425674, upload-time = "2026-07-04T17:07:02.387Z" }, - { url = "https://files.pythonhosted.org/packages/8b/0b/196350c122f50f6ca56846f2d71efd5e0d24b7b2e07355e019b2e2c7a11e/numpy-2.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f7feb014281029e628ba2d5a007407443b06e418b6fe451d1e2adcbc8eba0107", size = 10350256, upload-time = "2026-07-04T17:07:04.878Z" }, - { url = "https://files.pythonhosted.org/packages/db/f4/731b6085a83faf6ca843394cbd5e217280c214399f7e8b21b9f552af0ae2/numpy-2.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7c786fe9a5bbe360022e584c5a34cf6b54265c71bd7ec8ac3d8fec38968071f8", size = 16795063, upload-time = "2026-07-04T17:07:07.374Z" }, - { url = "https://files.pythonhosted.org/packages/bf/64/0e215f2048dd11a55bb989ed41b3585ef57452404e638d703a211a3e4157/numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32985c896d897419ef8da6917872d80b78ad0ea26d85b23245c7366ffde76d75", size = 11776652, upload-time = "2026-07-04T17:07:09.907Z" }, - { url = "https://files.pythonhosted.org/packages/b5/59/2b844c7a6e9deff69b404a66221e1542937734f65d5e6e39411876053862/numpy-2.5.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:efd736408cc97c79b9e6917338dfc8f06013b2274f992e96b1d9a81a71e2a2c2", size = 5335944, upload-time = "2026-07-04T17:07:12.227Z" }, - { url = "https://files.pythonhosted.org/packages/86/51/9bf7cb2cabcebc9e017e4ec7e6322b378317a542c08b4cb68479c1efc716/numpy-2.5.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ab84dc6b074fa881cae55bea94cc4f68e285181ba7f32497bf7dee6b1496165b", size = 6656266, upload-time = "2026-07-04T17:07:14.368Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/fb7615b211b82a32f44d5180a6d421b61f84d4fadd578b48ba4ac34e189f/numpy-2.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caf3e317d33d60c37986b452613f4ab51246d0691350c03d0cb4a898627f4a95", size = 15179720, upload-time = "2026-07-04T17:07:16.272Z" }, - { url = "https://files.pythonhosted.org/packages/41/5f/0f992cb24560673496c5d68de61913b57166ce530ffda07c1f280e0cc464/numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54ad769f17bc2d833b620851989f62054fb9ab93c969d9e1dc3c8e3d56beea21", size = 16664835, upload-time = "2026-07-04T17:07:19.021Z" }, - { url = "https://files.pythonhosted.org/packages/a2/2f/97d6475ee91afe2587797d09446f9d3e475ad4cb681662d824809327b75a/numpy-2.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c12afb53450fa976d4c681c50a7423729a4c51c0465ed9f32b8a9cabbc472373", size = 16539135, upload-time = "2026-07-04T17:07:22.015Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5b/4db81e4ba0be7e2776b1de68c82aa862c7f8ec27e1b4927d4ae075e20678/numpy-2.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c11c405efc5ff6816d5983c96cdfa215bab3428961243af3ff59b228490438", size = 18426684, upload-time = "2026-07-04T17:07:24.941Z" }, - { url = "https://files.pythonhosted.org/packages/1f/64/c0ba2d90724d450279a7df8f32057241070250a26a7e2b5337d77347f481/numpy-2.5.1-cp314-cp314-win32.whl", hash = "sha256:f2479a47f8d5932d1718168a681ad6e536a9df484c83cfcf9de365e164537ace", size = 6116103, upload-time = "2026-07-04T17:07:27.622Z" }, - { url = "https://files.pythonhosted.org/packages/c1/1a/837f9ed7405adcd7a40538792eb169eddd8fa5630c16a1ef49dae71a30f4/numpy-2.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:24d0eb82c0541d3415a33425db64ae439dffccd7b4dbcb30e7c35120205c506a", size = 12562177, upload-time = "2026-07-04T17:07:29.887Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/49707938b6dd0a78a9178dd93227dc89e4c11af47f5c798d70366e8d0483/numpy-2.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:5a4c988b38d261deeeaad9954e3deb091ad905c94e8bb6708654ef1d97f286b0", size = 10627739, upload-time = "2026-07-04T17:07:32.568Z" }, - { url = "https://files.pythonhosted.org/packages/a6/c7/bb4b882cfe7f299cbc8b66e42e7dd78cf9d14e40f9469fc5e3db7e15b3bd/numpy-2.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a33276be12fa045805f477f22482088b66bb758ffbe89a9d21457de863a32e22", size = 11894709, upload-time = "2026-07-04T17:07:34.941Z" }, - { url = "https://files.pythonhosted.org/packages/40/3f/5af7f4a7f6224aef48017aa82bb6174c7a659d724be0c75017b7e64a55b4/numpy-2.5.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f089d7b00756190aacf1f5d34bdf38c3c430ac82b4f868f8cede73380460fce7", size = 5453810, upload-time = "2026-07-04T17:07:37.495Z" }, - { url = "https://files.pythonhosted.org/packages/20/c9/3474309bc94d634d3f9c3eddf03250ecb8c22cd948ef16fef69a77cc5d7b/numpy-2.5.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:09e9bfd8d2cf479c7d174804fb3811c53a8e9f20a37444008606b57d6b7a826d", size = 6761189, upload-time = "2026-07-04T17:07:39.563Z" }, - { url = "https://files.pythonhosted.org/packages/90/8a/558ae39fdd55d7e7f7fef9a84a6e964ac6b23edbd2a07e52bb084500507d/numpy-2.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e68d8dd1e7eba712948f2053a29ec86917bc70ba1358df869d9f06649ef9cf09", size = 15225039, upload-time = "2026-07-04T17:07:41.682Z" }, - { url = "https://files.pythonhosted.org/packages/63/27/ca7392b2d030277bdf0273e7d23255b3ee57d57a7c170a6f4fb3981e1e5d/numpy-2.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d5095fa265a0c4152e7bb12759e14381ef5496152f1ce58f44bdf55c44beb4", size = 16701306, upload-time = "2026-07-04T17:07:44.611Z" }, - { url = "https://files.pythonhosted.org/packages/02/42/03d53ae7996c44d4374a8262e9dc41671fd56cbb98f7d47ef85cf5da4c6b/numpy-2.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ab87a91b3cc3382b8956095bd8f95e00cf679bb81554339be1a2ba404a1473c1", size = 16589955, upload-time = "2026-07-04T17:07:47.694Z" }, - { url = "https://files.pythonhosted.org/packages/7b/15/6c1784ae469640e65db111e9a34b3d0f14d91e8a38b9ce34810ced370dbb/numpy-2.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:224ca51130ef7da85bea2191625181cb4f337f9cb64b471f10c1a12aa8b60077", size = 18464252, upload-time = "2026-07-04T17:07:50.684Z" }, - { url = "https://files.pythonhosted.org/packages/94/a8/f98e50356cf167df656c526c2dfeec2d7dde182f2a3da4b458a5938e2776/numpy-2.5.1-cp314-cp314t-win32.whl", hash = "sha256:6eab239876581b2b3c5a242281b6007bbdbcd1c7085d7709bb57c5929b11e6bf", size = 6263298, upload-time = "2026-07-04T17:07:53.445Z" }, - { url = "https://files.pythonhosted.org/packages/72/ac/96ae880cdecad0b3275d9359fcec72667b49a4863c9f12942e43679dda02/numpy-2.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:83ce9c80d5b521b0d77ddcbe5447c218d247929b6cc056ca5351342accfff0af", size = 12748623, upload-time = "2026-07-04T17:07:55.384Z" }, - { url = "https://files.pythonhosted.org/packages/a1/5a/4d2b1601df3602dba7a14f3348ba9bfe94a18adb428e693df6154c293831/numpy-2.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:5a6db61f9aaa57e369905c67d852045d3c4f7126405b29d09b19dec118e9c9cb", size = 10697674, upload-time = "2026-07-04T17:07:58.506Z" }, -] - -[[package]] -name = "packaging" -version = "26.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, -] - -[[package]] -name = "pillow" -version = "12.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" }, - { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" }, - { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2d/ede717bc1144f63886c21fd349bb95860b0d1a21149ff16f2bb362b612b6/pillow-12.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd", size = 6934408, upload-time = "2026-07-01T11:53:53.487Z" }, - { url = "https://files.pythonhosted.org/packages/a3/48/9c58b685e69d49c31af6c8eb9012055fab7e665785165c84796e2c73ce72/pillow-12.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c", size = 6337160, upload-time = "2026-07-01T11:53:55.457Z" }, - { url = "https://files.pythonhosted.org/packages/ff/fa/dc2a5c0ba6df93f67c31d34b808b7ce440b40cdbf96f0b81cde1d1e6fa93/pillow-12.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5", size = 7045172, upload-time = "2026-07-01T11:53:57.736Z" }, - { url = "https://files.pythonhosted.org/packages/86/a5/444817a4d4c4c2417df00513086ca196f388d8f9ef40c2e4ccd1ad1af54b/pillow-12.3.0-cp311-cp311-win32.whl", hash = "sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b", size = 6472232, upload-time = "2026-07-01T11:53:59.767Z" }, - { url = "https://files.pythonhosted.org/packages/63/c6/4bad1b18d132a50b27e1365e1ab163616f7a5bb56d330f66f9d1d9d4f9d4/pillow-12.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a", size = 7233653, upload-time = "2026-07-01T11:54:02.066Z" }, - { url = "https://files.pythonhosted.org/packages/fd/16/00f91ab7760dc842f5aad55217e80fc4a7067a0604535249bc8a2d6d9870/pillow-12.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26", size = 2568195, upload-time = "2026-07-01T11:54:04.622Z" }, - { url = "https://files.pythonhosted.org/packages/37/bf/fb3ebff8ddcb76aac5a01389251bbbb9519922a9b520d8247c1ca864a25d/pillow-12.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965", size = 5345969, upload-time = "2026-07-01T11:54:06.397Z" }, - { url = "https://files.pythonhosted.org/packages/d8/66/9a386a92561f402389a4fc70c18838bf6d35eb5eb5c6850b4b2dc64f5048/pillow-12.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7", size = 4780323, upload-time = "2026-07-01T11:54:09.351Z" }, - { url = "https://files.pythonhosted.org/packages/25/27/ac8f99618ffd3dde21db0f4d4b1d2ab00c0880595bfd17df103f7f39fd0c/pillow-12.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9", size = 6266838, upload-time = "2026-07-01T11:54:11.71Z" }, - { url = "https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91", size = 6940830, upload-time = "2026-07-01T11:54:13.732Z" }, - { url = "https://files.pythonhosted.org/packages/eb/51/8b08617af3ad95e33ce6d7dd2c99ed6c8298f7fb131636303956be022e25/pillow-12.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c", size = 6344383, upload-time = "2026-07-01T11:54:15.756Z" }, - { url = "https://files.pythonhosted.org/packages/1d/72/cf78ac9780bb93c28328f408973845a309d4d145041665f734572ced1b52/pillow-12.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df", size = 7052934, upload-time = "2026-07-01T11:54:17.721Z" }, - { url = "https://files.pythonhosted.org/packages/20/20/25e0f4dc178a6bc0696793720055519a0de89e7661dae886992decbd2f81/pillow-12.3.0-cp312-cp312-win32.whl", hash = "sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f", size = 6472684, upload-time = "2026-07-01T11:54:19.839Z" }, - { url = "https://files.pythonhosted.org/packages/45/89/da2f7971a317f83d807fdd4065c0af40208e59e692cc43d315a71a0e96d1/pillow-12.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09", size = 7227137, upload-time = "2026-07-01T11:54:22.025Z" }, - { url = "https://files.pythonhosted.org/packages/de/47/4845a0a6c0dbf1db8456bd9fc791f13c5ced7ced20606d08a0aacfd25b49/pillow-12.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510", size = 2568267, upload-time = "2026-07-01T11:54:24.051Z" }, - { url = "https://files.pythonhosted.org/packages/9d/ac/31fb64e1e7efb5a4b50cd3d92049ba89ac6e4d8d3bb6a74e15048ca3353e/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89", size = 4161684, upload-time = "2026-07-01T11:54:25.934Z" }, - { url = "https://files.pythonhosted.org/packages/87/b4/9805e23d2b4d77842b468513841fda254ee42f0289d25088340e4ff46e2d/pillow-12.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace", size = 4255487, upload-time = "2026-07-01T11:54:27.935Z" }, - { url = "https://files.pythonhosted.org/packages/df/39/ecf519435a200c693fe053a6ee4d835b41cf963a4dfc2551c4e637cb2a71/pillow-12.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec", size = 3696433, upload-time = "2026-07-01T11:54:29.813Z" }, - { url = "https://files.pythonhosted.org/packages/42/92/2fc3ffad878ae8dd5469ec1bc8eb83b71f48e13efdf68f02709003982a32/pillow-12.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66", size = 5345889, upload-time = "2026-07-01T11:54:31.97Z" }, - { url = "https://files.pythonhosted.org/packages/10/76/8803c13605b763d33d156c4678fc77f8443389c0c51c8aef707bb02015f4/pillow-12.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35", size = 4780109, upload-time = "2026-07-01T11:54:34.026Z" }, - { url = "https://files.pythonhosted.org/packages/1f/01/e18aff37cb0b4aac47ac90f016d347a49aca667ef97f190b06ac2aabc928/pillow-12.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65", size = 6263736, upload-time = "2026-07-01T11:54:36.131Z" }, - { url = "https://files.pythonhosted.org/packages/f7/62/de5bdd77d935331f4f802edc11e4d82950f642caad6cb2f949837b8560e2/pillow-12.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3", size = 6937129, upload-time = "2026-07-01T11:54:38.216Z" }, - { url = "https://files.pythonhosted.org/packages/70/4d/105627a13300c5e0df1d174230b32fd1273062c96f7745fd552b945d1e1d/pillow-12.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a", size = 6339562, upload-time = "2026-07-01T11:54:40.354Z" }, - { url = "https://files.pythonhosted.org/packages/6b/1d/f13de01a553988ab895ba1c722e06cf3144d4f57656fd5b81b6d881f1179/pillow-12.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e", size = 7049439, upload-time = "2026-07-01T11:54:42.489Z" }, - { url = "https://files.pythonhosted.org/packages/c9/f9/066794cca041b969964f779ee5fa66a9498bbf34248ac39c5d7954e4198f/pillow-12.3.0-cp313-cp313-win32.whl", hash = "sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f", size = 6473287, upload-time = "2026-07-01T11:54:44.9Z" }, - { url = "https://files.pythonhosted.org/packages/a6/9b/7a58e61d62be561da3a356fe2384d4059a6345fc130e23ef1c36a5b81d24/pillow-12.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8", size = 7239691, upload-time = "2026-07-01T11:54:47.141Z" }, - { url = "https://files.pythonhosted.org/packages/aa/b0/c4ed4f0ef8f8fa5ee8351537db6650bb8189f7e118842978dd6589065692/pillow-12.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b", size = 2568185, upload-time = "2026-07-01T11:54:49.137Z" }, - { url = "https://files.pythonhosted.org/packages/dc/01/001f65b68192f0228cc1dbbc8d2530ab5d58b61037ba0587f946fea607cd/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330", size = 4161736, upload-time = "2026-07-01T11:54:51.156Z" }, - { url = "https://files.pythonhosted.org/packages/1a/d2/0219746d0fd16fc8a84498e79452375be3797d3ce4044596ce565164b84f/pillow-12.3.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217", size = 4255435, upload-time = "2026-07-01T11:54:53.414Z" }, - { url = "https://files.pythonhosted.org/packages/c8/02/8d0bc62ef0302318c46ff2a512822d2610e81c7aa46c9b3abe6cbaca5ad0/pillow-12.3.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930", size = 3696262, upload-time = "2026-07-01T11:54:55.739Z" }, - { url = "https://files.pythonhosted.org/packages/85/e2/73c77d218410b14f5f2d565e8a998d5317b7b9c75368d29985139f7a46f0/pillow-12.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8", size = 5350344, upload-time = "2026-07-01T11:54:57.657Z" }, - { url = "https://files.pythonhosted.org/packages/c7/da/32c752228ae345f489e3a42499d817b6c3996da7e8a3bc7a04fc806b243b/pillow-12.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0", size = 4780131, upload-time = "2026-07-01T11:54:59.713Z" }, - { url = "https://files.pythonhosted.org/packages/b1/9d/8b2c807dbef61a5197c047afe99823787eb66f63daf9fb2432f91d6f0462/pillow-12.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321", size = 6263757, upload-time = "2026-07-01T11:55:01.778Z" }, - { url = "https://files.pythonhosted.org/packages/5c/44/c85361f65dbe00eea8576ee467c768d25129989efb76e94f205e9ca9bb46/pillow-12.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b", size = 6936962, upload-time = "2026-07-01T11:55:03.93Z" }, - { url = "https://files.pythonhosted.org/packages/18/7e/e483414b35800b86b6f08dbbc7803fb5cd52c4d6f897f47d53ea2c7e6f65/pillow-12.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198", size = 6339171, upload-time = "2026-07-01T11:55:05.989Z" }, - { url = "https://files.pythonhosted.org/packages/f0/f4/68c491844841ede6bed70189546b3ee9731cf9f2cbad396faff5e1ccba45/pillow-12.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130", size = 7048116, upload-time = "2026-07-01T11:55:08.131Z" }, - { url = "https://files.pythonhosted.org/packages/a3/34/77f3f793fed8efc7d243f21b33c5a3f0d1c97ee70346d3db855587e155ff/pillow-12.3.0-cp314-cp314-win32.whl", hash = "sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a", size = 6467209, upload-time = "2026-07-01T11:55:10.408Z" }, - { url = "https://files.pythonhosted.org/packages/f1/e0/492879f69d94f91f60fc8cd05ba03650e9520afebb2fb7aa12777d7c7f38/pillow-12.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d", size = 7237707, upload-time = "2026-07-01T11:55:12.745Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ac/6b11f2875f1c2ac040d84e1bbf9cf22a88038f901ca1037898b280b38365/pillow-12.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838", size = 2565995, upload-time = "2026-07-01T11:55:14.736Z" }, - { url = "https://files.pythonhosted.org/packages/52/69/c2208e56af9bfc1913afb24020297a691eb1d4ef688474c8a04913f65e04/pillow-12.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e", size = 5352503, upload-time = "2026-07-01T11:55:17.076Z" }, - { url = "https://files.pythonhosted.org/packages/07/70/e5686d753e898a45d778ff1718dba8516ead6ab6b95d85fc8c4b70650cf2/pillow-12.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17", size = 4782956, upload-time = "2026-07-01T11:55:19.448Z" }, - { url = "https://files.pythonhosted.org/packages/d5/37/25c6692f06927ee973ff18c8d9ee98ad0b4d84ee67a09610c2dd1447958e/pillow-12.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385", size = 6322855, upload-time = "2026-07-01T11:55:21.613Z" }, - { url = "https://files.pythonhosted.org/packages/cc/91/420637fcb8f1bc11029e403b4538e6694744428d8246118e45719f944556/pillow-12.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c", size = 6989642, upload-time = "2026-07-01T11:55:24.006Z" }, - { url = "https://files.pythonhosted.org/packages/10/08/b94d7811281ccf0d143a1cf768d1c49e1e54af63e7b708ab2ee3eb87face/pillow-12.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d", size = 6391281, upload-time = "2026-07-01T11:55:26.252Z" }, - { url = "https://files.pythonhosted.org/packages/d2/87/24233f785f55474dc02ce3e739c5528a77e3a862e9333d1dd7a25cc31f70/pillow-12.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931", size = 7096716, upload-time = "2026-07-01T11:55:28.318Z" }, - { url = "https://files.pythonhosted.org/packages/23/26/fcb2f6e37175b04f53570b59937867e2b80ee1685e744023153028fc14f9/pillow-12.3.0-cp314-cp314t-win32.whl", hash = "sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7", size = 6474125, upload-time = "2026-07-01T11:55:30.956Z" }, - { url = "https://files.pythonhosted.org/packages/90/de/3634abee5f1c9e13c56787b7d5517b0ba8d6de51700b95578cf338349c9f/pillow-12.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c", size = 7242939, upload-time = "2026-07-01T11:55:34.044Z" }, - { url = "https://files.pythonhosted.org/packages/ce/2a/fd13f8eb24de5714a6eb444a3d67e2842c6c576e159a43793adf23051351/pillow-12.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45", size = 2567506, upload-time = "2026-07-01T11:55:35.988Z" }, - { url = "https://files.pythonhosted.org/packages/5d/dc/8fdce34ec725a33c81c6ba122b904d6b9024e50ea9ac7bede62fab54506c/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139", size = 4162063, upload-time = "2026-07-01T11:55:37.941Z" }, - { url = "https://files.pythonhosted.org/packages/76/66/2044b9a63d3b84ff048228dfcb7cd9bf0df983e8470971bf7d4c57b693de/pillow-12.3.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402", size = 4255549, upload-time = "2026-07-01T11:55:40.022Z" }, - { url = "https://files.pythonhosted.org/packages/52/7e/1f67e6f4ece6b582ee4b539decbcc9f848dc245a93ed8cd7338bafef72f1/pillow-12.3.0-cp315-cp315-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c", size = 3696331, upload-time = "2026-07-01T11:55:41.98Z" }, - { url = "https://files.pythonhosted.org/packages/12/40/d306fc2c8e4d45d7f175c77edca7063be7b86fe7fe6e68f4353bf71d808c/pillow-12.3.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f", size = 5350370, upload-time = "2026-07-01T11:55:44.028Z" }, - { url = "https://files.pythonhosted.org/packages/dd/44/668fb1437e8ce420f62d6106eb66e44a5971602a4d794615bdf79315d82d/pillow-12.3.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701", size = 4780147, upload-time = "2026-07-01T11:55:46.073Z" }, - { url = "https://files.pythonhosted.org/packages/0c/08/93fa2e70e30a2d81547e481b6ee2bb9522117221fb1e0ce4b5df70967677/pillow-12.3.0-cp315-cp315-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace", size = 6273659, upload-time = "2026-07-01T11:55:48.264Z" }, - { url = "https://files.pythonhosted.org/packages/f8/6d/043e96ff814fc31a33077e4cba86082167db520c93632afdf2042febbb0c/pillow-12.3.0-cp315-cp315-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4", size = 6947439, upload-time = "2026-07-01T11:55:50.503Z" }, - { url = "https://files.pythonhosted.org/packages/af/92/ba71d2ee2ac0edf3fa33bd9d5ee9ee080da70b1766f3ca3934f9938ddac9/pillow-12.3.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39", size = 6353577, upload-time = "2026-07-01T11:55:52.697Z" }, - { url = "https://files.pythonhosted.org/packages/0f/ce/e63064e2122923ff687c8ad792d0d736a7b3920a56a46982e81a7fdd25d6/pillow-12.3.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71", size = 7060394, upload-time = "2026-07-01T11:55:55.149Z" }, - { url = "https://files.pythonhosted.org/packages/54/76/a09cc3ccc8d773a7283d34c38bec1708f9e3cc932093cbc4c5e71ac4060b/pillow-12.3.0-cp315-cp315-win32.whl", hash = "sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827", size = 6467375, upload-time = "2026-07-01T11:55:57.769Z" }, - { url = "https://files.pythonhosted.org/packages/3e/03/1846c49ba3b1d5550392a4bbd06d6fb4578e1cd91a803198b5c90f5f7d53/pillow-12.3.0-cp315-cp315-win_amd64.whl", hash = "sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5", size = 7237048, upload-time = "2026-07-01T11:55:59.975Z" }, - { url = "https://files.pythonhosted.org/packages/fb/bb/89f35dcc79610423f9f195504d7def7f0d1416a711541b42867e25fe3412/pillow-12.3.0-cp315-cp315-win_arm64.whl", hash = "sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658", size = 2566006, upload-time = "2026-07-01T11:56:02.143Z" }, - { url = "https://files.pythonhosted.org/packages/30/88/707027ba09942dfa2c28759b5c222d769290a41c6d20ea60ec250801941f/pillow-12.3.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf", size = 5352509, upload-time = "2026-07-01T11:56:04.2Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6d/00352fa25332c2569cd387851f568cc5a4b75a9adbfb37ac4fbce4c02eec/pillow-12.3.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64", size = 4783167, upload-time = "2026-07-01T11:56:06.631Z" }, - { url = "https://files.pythonhosted.org/packages/13/4f/9e049dfa21af7c22427275720e2490267ba8138120add5c4c574deb69782/pillow-12.3.0-cp315-cp315t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e", size = 6329237, upload-time = "2026-07-01T11:56:08.868Z" }, - { url = "https://files.pythonhosted.org/packages/36/16/cf6eeaae8d0fce8dd390a33437cf68c5d5bd73834a2bc6e2f14efda0ab45/pillow-12.3.0-cp315-cp315t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777", size = 6997047, upload-time = "2026-07-01T11:56:11.379Z" }, - { url = "https://files.pythonhosted.org/packages/1e/69/dbf769bdd55f48bf5733cac28edc6364ffaa072ec9ba336266e4fe66be55/pillow-12.3.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1", size = 6400440, upload-time = "2026-07-01T11:56:13.908Z" }, - { url = "https://files.pythonhosted.org/packages/a0/e1/ffc9cfc2eea0d178da8018e18e959301ad9d6bc9f3edb7181e748a474b97/pillow-12.3.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9", size = 7105895, upload-time = "2026-07-01T11:56:16.575Z" }, - { url = "https://files.pythonhosted.org/packages/18/f0/a5595c1e8c3ae44b9828cb2f0fa8155e5095ef04d6327b8f61cf44a3df85/pillow-12.3.0-cp315-cp315t-win32.whl", hash = "sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8", size = 6474384, upload-time = "2026-07-01T11:56:18.855Z" }, - { url = "https://files.pythonhosted.org/packages/e4/04/62bcd9f844984c5938d3b05264a61d797a29d3e0812341a8204af70bbdee/pillow-12.3.0-cp315-cp315t-win_amd64.whl", hash = "sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418", size = 7243537, upload-time = "2026-07-01T11:56:21.214Z" }, - { url = "https://files.pythonhosted.org/packages/3d/68/1f3066acedf37673694a7141381d8f811ae97f30d34413d236abe7d489f1/pillow-12.3.0-cp315-cp315t-win_arm64.whl", hash = "sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59", size = 2567491, upload-time = "2026-07-01T11:56:23.506Z" }, - { url = "https://files.pythonhosted.org/packages/75/18/2e8b40223153ccbc60df07f9e8928dc0c76202aa4e55ae9f53962b6510d6/pillow-12.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468", size = 5302510, upload-time = "2026-07-01T11:56:25.736Z" }, - { url = "https://files.pythonhosted.org/packages/46/3e/51fabf59d5ab801ceab709453d3ab6b180083496579549de4c45ced6528a/pillow-12.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94", size = 4736058, upload-time = "2026-07-01T11:56:28.041Z" }, - { url = "https://files.pythonhosted.org/packages/bf/20/22fe9384b7949e25fb1293bcfc84fb82590ff4ea6b37c95b24d26d793d86/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e", size = 5237776, upload-time = "2026-07-01T11:56:30.263Z" }, - { url = "https://files.pythonhosted.org/packages/08/14/f6ba68107680ffa74b39985f3f30884e41318fbc4250caa423c79b4788bb/pillow-12.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3", size = 5860358, upload-time = "2026-07-01T11:56:32.68Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0169bc772ec491108b62f644f8ecf1fe5d8ae5ebafde2ee2142210166903/pillow-12.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a", size = 7231786, upload-time = "2026-07-01T11:56:35.046Z" }, -] - -[[package]] -name = "pyparsing" -version = "3.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - -[[package]] -name = "t4a-bench-report" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "matplotlib" }, - { name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" }, - { name = "numpy", version = "2.5.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" }, -] - -[package.metadata] -requires-dist = [ - { name = "matplotlib", specifier = ">=3.8" }, - { name = "numpy", specifier = ">=1.26" }, -]