Conversation
Codecov Report❌ Patch coverage is
... and 4 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Add a BUG (Basis-Update & Galerkin) time-evolution algorithm as a sibling of TDVP/TDVP2: struct + keyword constructor, docstring, module include, export, docs listing, changelog and bibliography entries. timestep! is a stub pending the implementation in the next commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement the fixed-rank BUG timestep! for FiniteMPS as a symmetric (2nd-order) composition of two rooted-TTN half-sweeps. Each first-order half-sweep evolves every site tensor exactly once: a K-step (basis update) at the leaf boundary and a forward Galerkin AC-step at every internal node, where the un-evolved old connecting tensor is reprojected onto the already-updated child bases via an accumulated basis-overlap transport tensor. Unlike TDVP there is no backward substep, so imaginary-time evolution stays stable. Adds the copying timestep wrapper and a test file mirroring the TDVP suite (energy conservation, eigenstate phase, TDVP agreement, 2nd-order convergence vs a dense reference, imaginary-time lowering, LazySum/MultipliedOperator). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add charge-sector coverage for the fixed-rank BUG using genuine symmetric tensors (U(1) Heisenberg in the Sz=0 and Sz=1 sectors, Z2 transverse-field Ising, SU(2) Heisenberg, and an imaginary-time U(1) run). Each asserts energy conservation, eigenstate phase, and preservation of the graded bond structure across the step. No implementation change was needed: the transport-tensor and adjoint machinery already handles graded/dual spaces correctly (design-doc risks H1/H6/H7 clear). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add _bug_augment_left/_bug_augment_right: state-preserving basis augmentation for rank-adaptive BUG. Given the old isometry U0 and the evolved single-site candidate K1, append the component of K1 orthogonal to U0 (via left_null/right_null! + catdomain/catcodomain, mirroring OptimalExpand's changebond!), keeping the old basis as the leading per-sector block so the reprojection stays exact. Returns the augmented isometry and the overlap M = U^* U0. Not yet wired into timestep!; unit tests cover both sweep directions, trivial and U(1) tensors, the old-first invariant per sector, range capture, rank growth, and a genuinely-new-sector case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wire rank-adaptivity into the BUG timestep!, gated on a truncating trscheme (the default notrunc() keeps the fixed-rank path byte-for-byte). Each adaptive half-sweep augments every internal bond with the new directions found by the evolved connecting tensor (old-basis-first, up to 2r) via _bug_augment_*, keeping the augmented basis so the next node's Galerkin fills the new directions; an optimal SvdCut compression after each half-sweep truncates the bonds back to the trscheme tolerance. In-place truncation of the augmented core cannot grow the bond (rank <= r), so truncation is deferred to the post-sweep compression. Environments recompute lazily. Tests: bond growth (tight vs loose tolerance), accuracy vs a dense reference improving monotonically as the tolerance shrinks, CBE-style tracking of a TDVP2 reference where fixed-rank BUG stays stuck, imaginary-time ground-state growth, and energy/norm behaviour under truncation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add symmetric + rank-adaptive coverage exercising the dynamic-grading path: total boundary charge preserved across rank-adaptive steps (Sz=0 and Sz=1), per-sector bond growth, time-dependent per-sector multiplicities, accuracy vs a dense reference improving as the tolerance shrinks, imaginary-time ground-state growth, and the H4 gate where a global rank cut truncates a whole charge sector to dimension 0 and subsequent steps run cleanly through the reduced grading. No implementation change needed; the augmentation/transport/SvdCut machinery handles graded bonds. Documented finding: single-site BUG does not recover a sector once truncated away (re-growth is expected to need the Stage-3 parallel coupling). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Describe the delivered BUG integrator (symmetric 2nd-order, no backward substep, rank-adaptive via a truncating trscheme) rather than just the struct. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring src/algorithms/timestep/bug.jl closer to tdvp.jl in structure and comment density, without changing the algorithm: - timestep!: drop the length(ψ)==1 branch and the fixed/adaptive if/else; two sweeps, each optionally followed by _bug_truncate! gated on _bug_truncates(alg). - Merge the four sweep helpers into two. The only fixed-vs-adaptive difference (install new isometry vs. augment old-first) is isolated into _bug_leftbasis/_bug_rightbasis; the leaf folds into a single loop+edge-case like TDVP, removing the separate envs_old. - Rewrite the transport helpers with partition-based multiplication (_transpose_tail/_mul_front + adjoint) instead of @Plansor with a hard-coded single physical index, so BUG now supports MPS with any number of physical legs. - Trim the augment/sweep comment blocks to TDVP density; augment helpers keep their (Û, M) return. All 140 BUG tests (bug.jl + bug_augment.jl) stay green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow TDVP's layout more closely: write both half-sweeps as inline loops plus edge cases directly in timestep!, dropping the _bug_sweep_right!/ _bug_sweep_left! helpers. The per-node basis update (_bug_leftbasis/ _bug_rightbasis) and transport helpers stay factored out, mirroring how TDVP keeps left_gauge/right_gauge as helpers while inlining the sweep loops. No behavior change; all 140 BUG tests stay green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fold _bug_leftbasis/_bug_rightbasis (fixed/adaptive basis dispatch), the transport contractions, and the SvdCut truncation directly into timestep!, so the integrator reads as one self-contained function. The per-node fixed vs. adaptive choice is now an inline `if truncates` branch, and the old→new transport is written inline (`U' * U₀` / `_transpose_tail(U₀) * _transpose_tail(U)'`), reusing the U₀ = (old isometry in the new frame) subexpression. Only _bug_augment_left/_bug_augment_right remain as named helpers, since test/algorithms/bug_augment.jl imports and asserts on them directly. Also refresh a stale test comment that referenced the removed _bug_transport_*. No behavior change; all 140 BUG tests stay green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_bug_augment_left/_bug_augment_right previously built the full orthogonal complement (left_null / right_null!), projected the candidate into it, orthonormalized, and mapped it back (N * Q) — two factorizations plus several contractions — and then computed an overlap M that every production call site discarded. Replace this with a single QR/LQ of the stacked [U₀ │ K₁]: orthonormalizing with U₀ first keeps it as the leading per-sector block and appends only the directions of K₁ orthogonal to it, while the factorization caps each charge sector at dim(Vl⊗P, c) so nothing outside the physical space is ever added (the property left_null used to guarantee). Drop the discarded M return; the augment test now forms M = Û'U₀ itself to check the old-first invariant. All 140 BUG tests stay green (energy conservation, rank-adaptive growth, U(1) symmetric, old-first augmentation invariants). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a `ParallelBUG <: Algorithm` for `FiniteMPS`: the parallel Basis-Update &
Galerkin integrator (Ceruti et al. 2024) specialized to the caterpillar tree.
All local problems read from one frozen `t0` snapshot (no sweep); the root
carries the amplitude, interior connecting tensors are evolved as isometries,
bonds are augmented old-first with a zeroed-corner coupling block, then cut back
by an SvdCut sweep.
Experimental. Verified behaviour (test/algorithms/parallelbug.jl, 37 passing):
- exact reproduction of the dense exp(-iH dt) step at two sites;
- energy + eigenstate-phase conservation (amplitude carried once, at the root);
- agreement with TDVP over short times;
- monotone imaginary-time energy lowering, norm-preserving;
- adaptive bond growth under a tight `trscheme`;
- U(1)/Z2 total-charge and graded-structure preservation.
Known gap (2 `@test_broken`): the documented first-order accuracy is not yet
attained for L > 2 (measured slope ~0). The coupling-block reconciliation
(M = U'U0, Ceruti et al. Alg. 4) is incomplete; the diagnosis and the path to
close it are in research/PARALLELBUG_{design,STATUS}.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Close the known first-order accuracy gap of the ParallelBUG integrator for L > 2 (the two accuracy gates were @test_broken, measured slope ~0). Two fixes, both pinned against Ceruti et al. 2024 (arXiv:2412.00858) Alg. 1-4: * Leaves-to-root reconciliation (Alg. 4): the first-order coupling block C̃ᵢ is stacked into the evolved tensor *before* orthonormalizing the new bond directions, so directions discovered deep in the chain propagate up through the spans. The interior tensors of the augmented state are pure isometries [old | Ũᵢ]; all amplitude and first-order content is carried by the root tensor [C̄_L(t₁); C̃_L]. The previous flat assembly placed the couplings in the (new-row, old-col) blocks, which routes them through the amplitude-carrying root block and suppresses them by the old bond matrix — the interior first-order terms effectively vanished. * Amplitude-weighted kets: the interior Galerkin solves and couplings act on the centers AC[i] (the paper's Y_τ⁰ = U_τ⁰S_τ⁰), not the bare isometries AL[i]; their amplitude/phase is discarded with the R-factor in the orthonormalization, so no overcounting occurs (this resolves the "full-environment effective Hamiltonian trilemma" of the design notes). The couplings are one-site effective derivatives against a mixed <augmented|H|old> left environment (two TransferMatrix applications per site), replacing the two-site AC2_hamiltonian objects; LazySum and MultipliedOperator are supported by mirroring the derivative-operator dispatch. The fixed-rank notrunc() path now restores the pre-step virtual space of every bond (per-bond truncspace) instead of a global truncrank(maximum(D)). Measured convergence slope 1.95-1.98 (assert > 0.8, at least the documented first order); the theta-scaling gate now compares against a theta -> 0 run of the same integrator, isolating the c*n*theta truncation term (5e-4 -> 2.5e-6 -> 1e-15). All 40 tests pass; both @test_broken gates flipped to @test. Still experimental: the frozen-snapshot local solves are executed serially and step rejection is not yet implemented (see research/PARALLELBUG_STATUS.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both Basis-Update & Galerkin integrators now live in
src/algorithms/timestep/bug.jl (sequential BUG first, then a Parallel BUG
section). The copying timestep wrapper, previously duplicated verbatim, is
shared via alg::Union{BUG, ParallelBUG}, and the single-use _pbug_truncates
predicate is inlined into _pbug_truncate!. No behavioural changes: both the
BUG and ParallelBUG test suites pass unchanged. Test files stay separate so
ParallelTestRunner keeps running them in parallel.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Compared against Ceruti et al. 2024 and the authors' reference
(github.com/JonasKu/Publication-Parallel-BUG-for-TTNs). The core assembly
matches on every load-bearing point; this lands the concrete gaps found:
- fix time-dependent coupling: `_pbug_coupling_hamiltonian` was applied with
the one-arg form (a MethodError for a genuine TimedOperator); apply two-arg
at the midpoint `t + dt/2` (the anchor `integrate` freezes coefficients at).
- thread phase-1's L independent local solves via `tmap!` gated on
`Defaults.scheduler[]`; warm the lazily-mutating finite environments serially
first (`_pbug_warmup_envs!`, dispatching through MultipleEnvironments).
- add the local error estimator `η = ‖C̃‖/dt` (eq. 6) and an opt-in
rank-saturation step-rejection retry (fields `c`, `maxiter_rejection`).
- type-stable assembly (`As`/`Cevo` no longer `Vector{Any}`).
- tests: TimedOperator, step rejection, linear error accumulation.
Deferred (documented in research/PARALLELBUG_STATUS.md): the second-order
augmented-Galerkin variant and the η-threshold / basis-enrichment retry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reverse-engineered the reference `TTN_integrator_parallel_2nd_order_nonglobal.m` (augmented-Galerkin: keeps the new-new corner `Ci = Δt·F` projected onto the new directions, a 3r core — NOT a Strang composition) and derived the MPS caterpillar mapping. Records why it is a substantial port (Tucker-tree core-at-every-node vs. MPS root-only amplitude ⇒ needs a full augmented-basis Galerkin sweep) and how to validate it (rank-limited err(order=2) < err(order=1); dt-slope ≈ 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implemented and rigorously tested the tractable route to a second-order variant (first-order 2r augmented basis + Galerkin core evolution on the augmented state's own environments). It is exact at 2 sites and ~2x more accurate than first order, but the measured LOCAL one-step error slope is ~2, not 3 -- a better-constant first-order scheme, not genuine second order -- so it was reverted rather than shipped mislabeled. A Galerkin core on the frozen 2r basis caps the local error at O(dt^2); genuine second order needs the reference's 3r augmentation that adds the new-new corner (Ci) directions to the basis and keeps their amplitude. Documented as the remaining path in the design note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the L>=3 throw with the genuine second-order assembly, specialized to the caterpillar rooted at the last site: enrich both bond bases to rank 2r with one H*psi0 application (Ubar0/Vbar0, folding the enriched environments by explicit transfer matrices so the zero-weight directions never collapse under canonicalization), run the 2r Galerkin K-steps freezing the enriched right basis Vbar0, and transport the evolved-amplitude coupling R = Utilde2' * Chat to the root through the frozen right isometries. The root core is the exact matrix S-hat assembly (the 2r Galerkin S-bar1 in the Ubar0 rows, the coupling in the Utilde2 rows, new-new corner zero), giving local error O(dt^3) -- uniform log-log slope ~= 3 vs the first-order ~= 2. Replaces the superseded _pbug_preaugment with _pbug2_assemble_core and its helpers. Swaps the ParallelBUG2 @test_throws for the decisive slope-~=3 gate at L=4,5 (full P^8) and L=6 (reduced P^4), plus energy/phase, TDVP agreement, imaginary-time lowering, and Z2 charge preservation. The first-order ParallelBUG and sequential BUG suites are unchanged and green. Plain Hamiltonians only (no LazySum) so far; still experimental. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring src/algorithms/timestep/bug.jl in line with the tdvp.jl house style without changing any behavior: trim the large in-code comment blocks and the ParallelBUG/ParallelBUG2 docstring essays to short comments, and remove the one-use helper proliferation. - drop the `_pbug_assemble` forwarding stubs; the assembly cores are now the dispatch targets `_pbug_assemble(::ParallelBUG)` / `_pbug_assemble(::ParallelBUG2)` - collapse the two `_pbug_with_rejections` methods into one generic `typeof(alg)` rebuild - inline `_pbug_overwrite!`, `_pbug2_embed`, and `_pbug2_newdirs_right` into their sole call sites Genuinely reused helpers are kept: `_bug_augment_left/right` (unit-tested), `_pbug_newdirs`/`_pbug_stack_child`/`_pbug_truncate!`, the LazySum dispatch families, and the `_pbug2_left/right_enrich` subroutines. All BUG, ParallelBUG, and ParallelBUG2 test suites pass unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a (very WIP) implementation of the BUG integrators by the Lubich group. There are two main motivations for this:
I still need to clean this up and verify most of the code, but at least it looks like the tests are passing, so if nothing else this is an accidentally correct integrator.