open-standards/wai/wai-quantum/examples/tdvp_quench.rs
Transaction Science e2a6baa5b1
Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
no-vanity-metrics / WAI public text names no comparison (pull_request) Successful in 3s
no-vanity-metrics / WAI public text names no company or product (pull_request) Successful in 3s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m58s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m30s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m16s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m11s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m40s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 4m29s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 12s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 2m11s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 29s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 46s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 1m31s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 1m4s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m2s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 3m56s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 1m45s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m41s
standards workspaces build + test / aac-rs (pull_request) Successful in 1m37s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m0s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 41s
standards workspaces build + test / map-rs (pull_request) Successful in 41s
standards workspaces build + test / mesh-rs (pull_request) Successful in 34s
standards workspaces build + test / openpay (pull_request) Successful in 2m7s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 6m5s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 34s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 2m9s
standards workspaces build + test / arl-rs (pull_request) Successful in 3m57s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 3m58s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 4m0s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 3m53s
standards workspaces build + test / sense-rs (pull_request) Successful in 3m57s
standards workspaces build + test / macOS energy backends (pull_request) Failing after 6m44s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 8m36s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 35s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 3m2s
wai-quantum 0.3.35: time evolution of spin chains by TDVP, held to exact answers
quantum_tdvp evolves a matrix-product state by the two-site time-dependent
variational principle, a symmetric second-order sweep:
- each bond goes forward half a step under its effective Hamiltonian, and the
  new centre goes back half a step under its one-site one;
- the exponentials are Lanczos with full re-orthogonalisation, and a step
  that does not converge is halved;
- bonds are split by a Jacobi SVD, so amplitudes resolve to rounding;
- every bond's basis is completed with null vectors up to max_bond, which
  removes the projection error a product state's small bonds would cause.

The referees are exact Krylov evolution of all amplitudes (up to 20 sites) and
the free-fermion Ising quench at any length, including the Loschmidt echo.

Checked:
- complete bases are exact to rounding at any step size;
- at 100 sites and bond 64 the critical quench stays within 1e-9 of the exact
  answer through t = 3, and past that the error follows the reported
  discarded weight;
- runs are bit-identical across thread counts and natively vs wasm32-wasip2
  (new pin);
- the CLI command tdvp prints the same bytes natively and under WASI.

A fourth-order Yoshida composition was measured as less accurate and slower,
and was removed; the module docs record why.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 11:13:38 -04:00

54 lines
2.6 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! A quench of the transverse-field Ising chain by TDVP, held at every
//! report to the exact free-fermion solution: the chain starts with every
//! σˣ = +1 and evolves under `−J Σ σᶻσᶻ − h Σ σˣ`.
//!
//! ```text
//! cargo run --release --example tdvp_quench --features quantum_tdvp -- N BOND DT T [h] [cutoff] [threads]
//! ```
use wai_quantum::quantum_dmrg::{Chain, Mps, Op, Scalar, C};
use wai_quantum::quantum_tdvp::{ising_quench, Evolution, TdvpConfig};
fn main() {
let a: Vec<String> = std::env::args().collect();
let n: usize = a[1].parse().unwrap();
let bond: usize = a[2].parse().unwrap();
let dt: f64 = a[3].parse().unwrap();
let t_end: f64 = a[4].parse().unwrap();
let h: f64 = a.get(5).map_or(1.0, |x| x.parse().unwrap());
let cutoff: f64 = a.get(6).map_or(1e-20, |x| x.parse().unwrap());
let threads: usize = a.get(7).map_or(TdvpConfig::default().threads, |x| x.parse().unwrap());
let chain = Chain::ising(n, 1.0, h);
let plus = Mps::product(&vec![[C { re: 1.0, im: 0.0 }, C { re: 1.0, im: 0.0 }]; n]);
let cfg = TdvpConfig { dt, max_bond: bond, cutoff, threads, ..TdvpConfig::default() };
let mut ev = Evolution::new(&chain, &plus, cfg);
let e0 = ev.energy();
let steps = (t_end / dt).round() as usize;
let every = ((0.5 / dt).round() as usize).max(1);
let t0 = std::time::Instant::now();
let mut discarded = 0.0;
println!("ising n={n} h={h} bond={bond} dt={dt} cutoff={cutoff:e}");
println!(" t max|Δσˣ| max|Δσᶻσᶻ| σˣ(mid) exact rate exact rate S(mid) bond |ΔE| discarded seconds");
for s in 1..=steps {
discarded += ev.step().discarded;
if s % every == 0 || s == steps {
let t = ev.time();
let ff = ising_quench(n, 1.0, h, t);
let x = ev.expect(Op::x());
let zz = ev.bond_expect(Op::z(), Op::z());
let dx = x.iter().zip(&ff.x).map(|(p, q)| (p - q).abs()).fold(0.0, f64::max);
let dzz = zz.iter().zip(&ff.zz).map(|(p, q)| (p - q).abs()).fold(0.0, f64::max);
let echo = ev.overlap(&plus).norm2();
let rate = -echo.ln() / n as f64;
let exact_rate = -ff.echo.ln() / n as f64;
let s_mid = ev.entropies()[n / 2 - 1];
println!(
"{t:5.2} {dx:.2e} {dzz:.2e} {:+.10} {:+.10} {rate:.8} {exact_rate:.8} {s_mid:.4} {:4} {:.1e} {discarded:.1e} {:.1}",
x[n / 2],
ff.x[n / 2],
ev.max_bond(),
(ev.energy() - e0).abs(),
t0.elapsed().as_secs_f64()
);
}
}
}