Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ repos:
rev: v2.0.1
hooks:
- id: runic
args: [--docstrings]
230 changes: 230 additions & 0 deletions docs/DOCSTRING_STYLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
# Docstring style guide

This document defines the conventions for docstrings across MPSKit.jl.
The goal is a single, uniform presentation for all public-facing functionality, so that the API reference reads as one coherent whole.

These rules apply to **every** docstring in `src/`, exported or not.
Not every symbol needs every section — pick the template that fits (see [Templates](#templates)) — but when a docstring documents arguments, returns, fields, examples, or references, it does so in the one format described here.

## Quick rules

- **Section headers use a single hash** (`# Arguments`, `# Returns`), matching Julia Base.
- **Leave a blank line after every section header**, before the bullets, prose, or signature block that follows.
- **Bullet entries** are `` - `name`: description `` — a dash, the name in backticks, a colon, one space, then the description. Add the type (`` `name::Type` ``) only when it is helpful.
- **Cross-references** use `[`name`](@ref)` for internal symbols and `[`name`](@extref Pkg.name)` for symbols in other packages.
- **Type parameter lists** put a space after each comma: `Array{T, N}`, `Union{A, B, C}` — never `Array{T,N}`.
- **Default values** put spaces around the `=`: `tol = 1e-10`, not `tol=1e-10`.
- **Literature references** use `@cite` keys, never inline DOIs or URLs.
- **Examples** that show output are runnable `jldoctest` blocks.
- **Caveats** use `!!! note`; **unstable or experimental** features use `!!! warning`.

## Section headers

Use a single hash (`#`) for all section headers inside a docstring.
The canonical section names, in the order they should appear, are:

1. `# Constructors` — constructor signatures (container types with non-trivial constructors).
2. `# Arguments` — positional arguments.
3. `# Keyword Arguments` — keyword arguments.
4. `# Returns` — the return value(s).
5. `# Fields` — the struct fields, when the raw fields are the public API (algorithm structs; rendered by `$(TYPEDFIELDS)`).
6. `# Properties` — the `getproperty` interface, when it differs from the raw storage (e.g. the gauge views of an MPS container). Use `# Fields` **or** `# Properties`, whichever describes the public surface — not both.
7. `# Notes` — conventions and caveats worth a dedicated block.
8. `# Examples` — runnable examples.
9. `# See also` — related functions; for an algorithm struct, the driver(s) that consume it.
10. `# References` — literature citations.

Omit any section that does not apply.
Do not use `## Arguments` (double hash), `# Keywords`, or other spellings.
Always follow a section header with a blank line, so every section reads the same way:

```
# Keyword Arguments

- `tol = 1e-10`: convergence tolerance
```

For docstrings long enough to warrant it, split off detail into a `# Extended help` section (a Julia Base convention) so the summary line and first paragraph stay terse.

## Bullet format

Document arguments, keyword arguments, returns, and manually-listed properties as bullet lists in this form:

```
- `name`: description
- `name::Type`: description
```

A dash (not `*`), the name in backticks, a colon **with no leading space**, one trailing space, then the description.

Include the type in the backtick span **only when it earns its place** — when it constrains what the caller may pass or disambiguates an overloaded name (e.g. `` `O::Union{AbstractMPO, Pair, AbstractTensorMap}` ``).
Omit it when the type is obvious from the name, the surrounding prose, or the default value (e.g. `` `verbosity`: how much information is displayed ``).
Never repeat a type that `$(TYPEDFIELDS)` already renders from the struct definition.

Give keyword arguments their default in the backtick span when it is informative, with spaces around the `=`: `` - `tol = 1e-10`: convergence tolerance ``.
Always put spaces around `=` when writing a default value in a docstring (both in bullet entries and in signature blocks), even where the underlying code omits them.
Continuation lines of a long description are indented to align under the description text.

## Cross-references and citations

- Internal symbols: `` [`find_groundstate`](@ref) ``.
- External symbols: `` [`Householder`](@extref MatrixAlgebraKit.Householder) ``.
Note the parentheses — `@extref` only expands the `[text](@extref target)` form, not `[text][target]`.
- Literature: `[Zauner-Stauber et al. Phys. Rev. B 97 (2018)](@cite zauner-stauber2018)`, with the key defined in the bibliography.
Do not paste raw DOIs or arXiv links.

## Templates

Three templates cover the whole package.
Choose by what the symbol is, not by how important it is.

There are two flavours of type docstring — pick by what the type is.
Algorithm and configuration structs (`A1`) are keyword-configured bags of settings; container/data types (`A2`) hold state and are built through hand-written constructors.

### Template A1 — algorithm and configuration structs

For the keyword-configured `@kwdef` structs: every `Algorithm` subtype, and any similar options struct.
Each field carries a per-field string literal so that `$(TYPEDFIELDS)` renders the field documentation, including its type — the doc strings themselves do not repeat the type.

```julia
"""
$(TYPEDEF)

One paragraph: what the algorithm does and how.

# Fields

$(TYPEDFIELDS)

# See also

Used as the `algorithm` argument of [`find_groundstate`](@ref) and [`leading_boundary`](@ref).

# References

* [Author et al. Journal (Year)](@cite key)
"""
@kwdef struct VUMPS <: Algorithm
"tolerance for convergence criterium"
tol::Float64 = 1e-10
"maximal amount of iterations"
maxiter::Int = 200
end
```

`$(TYPEDEF)` generates the type signature — do not hand-write it.
The keyword constructor generated by `@kwdef` *is* the field list, so there is no `# Constructors` section; add one only if the type also offers a non-obvious convenience constructor.
`# See also` names the driver function(s) that accept the struct, so the algorithm is discoverable from its own page.
`# References` is optional and only appears when there is literature to cite.

### Template A2 — container and data types

For state-holding types with hand-written constructors: `FiniteMPS`, `InfiniteMPS`, `WindowMPS`, the MPO types, and similar.
Here the raw fields are internal; document the public `getproperty` interface under `# Properties`, and the constructors explicitly.

```julia
"""
$(TYPEDEF)

Type that represents a finite Matrix Product State.

# Constructors

FiniteMPS([f, eltype], physicalspaces, maxvirtualspaces; kwargs...)
FiniteMPS([f, eltype], N, physicalspace, maxvirtualspaces; kwargs...)
FiniteMPS(As::Vector{<:GenericMPSTensor}; kwargs...)

Construct an MPS from physical and virtual spaces, or from a list of tensors `As`.

# Arguments

- `As`: vector of site tensors
- `f = rand`: initializer for tensor data
- `physicalspaces`: list of physical spaces

# Keyword Arguments

- `normalize = true`: normalize the constructed state
- `left`: left-most virtual space

# Properties

- `AL`: left-gauged MPS tensors
- `AR`: right-gauged MPS tensors
- `AC`: center-gauged MPS tensors
- `C`: gauge (bond) tensors

# Notes

By convention, `AL[i] * C[i] == AC[i] == C[i-1] * AR[i]`.
"""
```

Use `$(TYPEDEF)` for the top line here too, so the type signature never drifts from the definition.
The constructors are the user-facing interface and are documented separately: stack their signatures as an indented code block under `# Constructors`, then document their parameters in flat sibling `# Arguments` / `# Keyword Arguments` sections (not nested `### ` sub-headers).

### Template B — full-contract functions

Use for the user-facing verbs: `find_groundstate`, `leading_boundary`, `timestep`, `time_evolve`, `expectation_value`, `changebonds`, `approximate`, `correlator`, and the like.

```julia
"""
funcname(ψ₀, H, [environments]; kwargs...) -> (ψ, environments, ϵ)

One paragraph describing the operation.

# Arguments

- `ψ₀::AbstractMPS`: initial guess
- `H::AbstractMPO`: the operator

# Keyword Arguments

- `tol::Float64 = 1e-10`: convergence tolerance

# Returns

- `ψ::AbstractMPS`: the converged state
- `ϵ::Float64`: final error estimate

# Examples

```jldoctest
julia> # runnable example
```

# References

* [...](@cite key)
"""
```

The top line is an indented, four-space signature; stack multiple overloads as separate signature lines.
Keep the `-> (...)` return annotation on the signature even when a `# Returns` section is present: the signature is the glanceable form, the section is the contract.
Omit any section that does not apply (a function with no keywords has no `# Keyword Arguments`).

### Template C — lightweight

Use for simple helpers and most internal functions: a signature and a one- or two-sentence description, no sections.

```julia
"""
correlator(ψ, O1, O2, i, j)
correlator(ψ, O12, i, j)

Compute the 2-point correlator `⟨ψ|O1[i]O2[j]|ψ⟩`.
Also accepts a range for `j`.
"""
```

## Admonitions

- `!!! note` for caveats and conventions the reader must know (e.g. gauge conventions).
- `!!! warning` for anything unstable or experimental — everything in `lib/internals`, current GPU support, and any feature that may change.

## Attachment

- Prefer a leading `"""..."""` block directly above the definition.
- Use `@doc (@doc a) b` only to alias a genuinely identical docstring onto a sibling.
- A comment between the docstring and the definition silently detaches the docstring; keep them adjacent and put any comment above the docstring.
- Do not put an HTML comment inside a docstring: DocumenterVitepress escapes it, so `<!-- ... -->` renders as visible body text on the page.
16 changes: 15 additions & 1 deletion docs/src/assets/mpskit.bib
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ @article{devos2022
abstract = {We calculate the Haldane gap of the SU⁡(3) spin [300] Heisenberg model using variational uniform fully symmetric SU⁡(3) matrix product states, and find that the minimal gap {$\Delta$}/{$J$}=0.0263 is obtained in the [210] sector at momentum 2⁢{$\pi$}/3. We also discuss the symmetry protected topological order of the ground state, and determine the full dispersion relation of the elementary excitations and the correlation lengths of the system.}
}

@article{gleis2023,
title = {Controlled {{Bond Expansion}} for {{Density Matrix Renormalization Group Ground State Search}} at {{Single-Site Costs}}},
author = {Gleis, Andreas and Li, Jheng-Wei and {von Delft}, Jan},
year = {2023},
month = jun,
journal = {Physical Review Letters},
volume = {130},
number = {24},
pages = {246402},
publisher = {American Physical Society},
doi = {10.1103/PhysRevLett.130.246402},
url = {https://link.aps.org/doi/10.1103/PhysRevLett.130.246402}
}

@article{haegeman2011,
title = {Time-{{Dependent Variational Principle}} for {{Quantum Lattices}}},
author = {Haegeman, Jutho and Cirac, J. Ignacio and Osborne, Tobias J. and Pi{\v z}orn, Iztok and Verschelde, Henri and Verstraete, Frank},
Expand Down Expand Up @@ -931,7 +945,7 @@ @article{zong2026pseudogap
archiveprefix = {arXiv}
}

@article{Hubig2015,
@article{hubig2015,
title = {Strictly single-site DMRG algorithm with subspace expansion},
author = {Hubig, C. and McCulloch, I. P. and Schollw\"ock, U. and Wolf, F. A.},
journal = {Phys. Rev. B},
Expand Down
27 changes: 14 additions & 13 deletions src/algorithms/ED.jl
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
"""
exact_diagonalization(H::FiniteMPOHamiltonian;
sector=rightunit(H),
len::Int=length(H), num::Int=1, which::Symbol=:SR,
alg=Defaults.alg_eigsolve(; dynamic_tols=false))
-> vals, state_vecs, convhist
exact_diagonalization(
H::FiniteMPOHamiltonian;
sector = rightunit(H), num::Int = 1, which::Symbol = :SR,
alg = Defaults.alg_eigsolve(; dynamic_tols = false)
) -> vals, state_vecs, convhist

Use [`KrylovKit.eigsolve`](@extref) to perform exact diagonalization on a
`FiniteMPOHamiltonian` to find its eigenvectors as `FiniteMPS` of maximal rank, essentially
equivalent to dense eigenvectors.

### Arguments
# Arguments

- `H::FiniteMPOHamiltonian`: the Hamiltonian to diagonalize.

### Keyword arguments
- `sector=rightunit(H)`: the total charge of the
# Keyword Arguments

- `sector = rightunit(H)`: the total charge of the
eigenvectors, which is chosen trivial by default.
- `len::Int=length(H)`: the length of the system.
- `num::Int=1`: the number of eigenvectors to find.
- `which::Symbol=:SR`: the kind eigenvalues to find, see [`KrylovKit.eigsolve`](@extref).
- `alg=Defaults.alg_eigsolve(; dynamic_tols=false)`: the diagonalization algorithm to use,
- `num::Int = 1`: the number of eigenvectors to find.
- `which::Symbol = :SR`: the kind eigenvalues to find, see [`KrylovKit.eigsolve`](@extref).
- `alg = Defaults.alg_eigsolve(; dynamic_tols = false)`: the diagonalization algorithm to use,
see [`KrylovKit.eigsolve`](@extref).

!!! note "Valid `sector` values"
The total charge of the eigenvectors is imposed by adding a charged auxiliary space as
the leftmost virtualspace of each eigenvector. Specifically, this is achieved by passing
`left=Vect[typeof(sector)](sector => 1)` to the [`FiniteMPS`](@ref) constructor. As
`left = Vect[typeof(sector)](sector => 1)` to the [`FiniteMPS`](@ref) constructor. As
such, the only valid `sector` values (i.e. `sector` values for which the corresponding
eigenstates have valid fusion channels) are those that occur in the dual of the fusion
of all the physical spaces in the system.
Expand Down
9 changes: 6 additions & 3 deletions src/algorithms/approximate/approximate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ of an MPS, using initial guess `ψ₀`. If only a state `ψ` is supplied instead
**Not every algorithm supports every combination of arguments below** — see the per-algorithm
notes at the end of this docstring before picking one.

## Arguments
# Arguments

- `ψ₀::AbstractMPS`: initial guess of the approximated state
- `(O::AbstractMPO, ψ::AbstractMPS)`: operator `O` and state `ψ` to be approximated
- `ψ::AbstractMPS`: state to be approximated directly (without an operator)
- `algorithm`: approximation algorithm. See below for a list of available algorithms.
- `[environments]`: MPS environment manager

## Keywords
# Keyword Arguments

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
Expand All @@ -33,7 +35,8 @@ struct itself instead (e.g. `DMRG(; tol, maxiter, verbosity)`).
- `trunc`: 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
# Algorithms

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
Expand Down
20 changes: 10 additions & 10 deletions src/algorithms/approximate/zipup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,10 @@ the in-place version simply uses `ψ` as the destination of the sweep, overwriti
The out-of-place version allocates a destination with the promoted scalar type of `O` and `ϕ`.
Both return the truncation error `ϵ` alongside the approximated state.

## Fields
# Constructors

$(TYPEDFIELDS)

## Constructors

Zipup(; trunc, alg_svd=Defaults.alg_svd(), left_to_right=true)
Zipup(alg_zipup, [alg_zipdown]; left_to_right=true)
Zipup(; trunc, alg_svd = Defaults.alg_svd(), left_to_right = true)
Zipup(alg_zipup, [alg_zipdown]; left_to_right = true)

Create a `Zipup` algorithm with the given truncated gauge algorithm, or by passing a truncation scheme and singular value decomposition algorithm.
The keyword `trunc` can be either one truncation strategy for a single zip-up sweep, or a tuple `(zipup_trunc, zipdown_trunc)` for a zip-up sweep followed by a zip-down sweep.
Expand All @@ -30,10 +26,14 @@ The keyword `left_to_right` selects the direction of the zip-up sweep, the zip-d

Following Paeckel et al., if the desired final bond dimension is `D`, one can use a more permissive zip-up truncation, e.g. rank `2D` with stricter tolerances, and use `alg_zipdown` to impose the final truncation.

## References
# Fields

$(TYPEDFIELDS)

# References

- [Stoudenmire and White New J. Phys. 12 (2010)](@cite stoudenmire2010)
- [Paeckel et al. Ann. of Phys. 411 (2019)](@cite paeckel2019)
* [Stoudenmire and White New J. Phys. 12 (2010)](@cite stoudenmire2010)
* [Paeckel et al. Ann. of Phys. 411 (2019)](@cite paeckel2019)
"""
struct Zipup{
U <: MatrixAlgebraKit.TruncatedAlgorithm,
Expand Down
Loading
Loading