diff --git a/src/algorithms/approximate/approximate.jl b/src/algorithms/approximate/approximate.jl index f28e67e6b..6967dcef0 100644 --- a/src/algorithms/approximate/approximate.jl +++ b/src/algorithms/approximate/approximate.jl @@ -1,13 +1,17 @@ @doc """ - approximate(ψ₀, (O, ψ), algorithm, [environments]; kwargs...) -> (ψ, environments) - approximate!(ψ₀, (O, ψ), algorithm, [environments]; kwargs...) -> (ψ, environments) - approximate(ψ₀, ψ, algorithm, [environments]; kwargs...) -> (ψ, environments) - approximate!(ψ₀, ψ, algorithm, [environments]; kwargs...) -> (ψ, environments) + approximate(ψ₀, (O, ψ), [environments]; kwargs...) -> (ψ, environments, ϵ) + approximate(ψ₀, (O, ψ), algorithm, [environments]) -> (ψ, environments, ϵ) + approximate!(ψ₀, (O, ψ), algorithm, [environments]) -> (ψ, environments, ϵ) + approximate(ψ₀, ψ, algorithm, [environments]) -> (ψ, environments, ϵ) + approximate!(ψ₀, ψ, algorithm, [environments]) -> (ψ, environments, ϵ) Compute an approximation to the application of an operator `O` to the state `ψ` in the form of an MPS `ψ₀`. If only a state `ψ` is supplied instead of the `(O, ψ)` pair, `ψ₀` is approximated directly to `ψ` (i.e. `O` is taken to be the identity). +**Not every algorithm supports every combination of arguments below** — see the per-algorithm +notes at the end of this docstring before picking one. + ## Arguments - `ψ₀::AbstractMPS`: initial guess of the approximated state - `(O::AbstractMPO, ψ::AbstractMPS)`: operator `O` and state `ψ` to be approximated @@ -16,17 +20,33 @@ approximated directly to `ψ` (i.e. `O` is taken to be the identity). - `[environments]`: MPS environment manager ## Keywords +The keyword-based call (no explicit `algorithm`) is a convenience method that picks an +algorithm for you based on the type of `ψ₀` (`DMRG`/`DMRG2` for a finite MPS, `VOMPS`/`IDMRG`/ +`IDMRG2` for an infinite MPS) and only accepts the `(O, ψ)` tuple form of `toapprox`. Once you +pass an explicit `algorithm`, keywords are no longer accepted here — configure the algorithm +struct itself instead (e.g. `DMRG(; tol, maxiter, verbosity)`). - `tol::Float64`: tolerance for convergence criterium - `maxiter::Int`: maximum amount of iterations - `verbosity::Int`: display progress information +- `trscheme`: if supplied, a truncated two-site sweep (`DMRG2`/`IDMRG2`) is prepended to + refine the bond dimension before the single-site algorithm polishes the result. ## Algorithms -- `DMRG`: Alternating least square method for maximizing the fidelity with a single-site scheme. -- `DMRG2`: Alternating least square method for maximizing the fidelity with a two-site scheme. +Each algorithm below only supports a subset of the general interface. Check this table before +picking one — in particular, note that **only `DMRG`/`DMRG2` accept a bare state `ψ`**; the +infinite algorithms always require an explicit `(O, ψ)` tuple, and **`VOMPS` has no in-place +`approximate!`** at all. + +| Algorithm | Scheme | State `ψ₀` | bare `ψ` allowed? | `approximate!` | +|:--------- |:----------------------------- |:---------------------------------- |:------------------:|:--------------:| +| `DMRG` | single-site, fixes bond dim | `AbstractFiniteMPS` | ✅ | ✅ | +| `DMRG2` | two-site, truncates via `trscheme` | `AbstractFiniteMPS` | ✅ | ✅ | +| `IDMRG` | single-site, thermodynamic limit | `InfiniteMPS` / `MultilineMPS` | ❌ (tuple only) | ✅ | +| `IDMRG2` | two-site, thermodynamic limit, needs unit cell ≥ 2 | `InfiniteMPS` / `MultilineMPS` | ❌ (tuple only) | ✅ | +| `VOMPS` | tangent-space truncation | `InfiniteMPS` / `MultilineMPS` | ❌ (tuple only) | ❌ (out-of-place only) | -- `IDMRG`: Variant of `DMRG` for maximizing fidelity density in the thermodynamic limit. -- `IDMRG2`: Variant of `DMRG2` for maximizing fidelity density in the thermodynamic limit. -- `VOMPS`: Tangent space method for truncating uniform MPS. +`InfiniteMPS`/`InfiniteMPO` inputs are converted internally to `MultilineMPS`/`MultilineMPO` +for `IDMRG`, `IDMRG2`, and `VOMPS`; you can also pass those types directly. """ approximate, approximate! @@ -35,6 +55,30 @@ approximate, approximate! _environment_args(Oϕ::Tuple) = Oϕ _environment_args(ϕ) = (ϕ,) +function approximate( + ψ::AbstractMPS, toapprox::Tuple{<:AbstractMPO, <:AbstractMPS}, + envs::AbstractMPSEnvironments = environments(ψ, toapprox...); + tol = Defaults.tol, maxiter = Defaults.maxiter, + verbosity = Defaults.verbosity, trscheme = nothing + ) + if isa(ψ, InfiniteMPS) + alg = VOMPS(; tol, verbosity, maxiter) + if !isnothing(trscheme) + alg = IDMRG2(; tol = min(1.0e-2, 100tol), verbosity, trscheme) & alg + end + elseif isa(ψ, AbstractFiniteMPS) + alg = DMRG(; tol, maxiter, verbosity) + if !isnothing(trscheme) + alg = DMRG2(; tol = min(1.0e-2, 100tol), verbosity, trscheme) & alg + end + else + throw(ArgumentError("Unknown input state type")) + end + + return approximate(ψ, toapprox, alg, envs) +end + + # implementation in terms of Multiline function approximate( ψ::InfiniteMPS, toapprox::Tuple{<:InfiniteMPO, <:InfiniteMPS}, algorithm, diff --git a/src/algorithms/unionalg.jl b/src/algorithms/unionalg.jl index 3e37f67f4..9ef7f722a 100644 --- a/src/algorithms/unionalg.jl +++ b/src/algorithms/unionalg.jl @@ -32,3 +32,8 @@ function find_groundstate(state, H, alg::UnionAlg, envs = environments(state, H, state, envs = find_groundstate(state, H, alg.alg1, envs) return find_groundstate(state, H, alg.alg2, envs) end + +function approximate(state, toapprox, alg::UnionAlg, envs = enviroments(state, toapprox...)) + state, envs = approximate(state, toapprox, alg.alg1, envs) + return approximate(state, toapprox, alg.alg2, envs) +end