Skip to content

Saving and loading

The examples on this page use MPSKit.jl and TensorKit.jl. See Installation for how to add these packages to your environment.

MPSKit does not ship its own save/load functions. States such as FiniteMPS and InfiniteMPS are ordinary Julia objects that wrap TensorKit TensorMaps, so any general-purpose Julia serializer stores and restores them. Two options cover essentially all use cases:

  • Serialization — a standard-library module, always available, no extra dependency. Best for quick "save a result and pick it up in the next session" workflows. Its file format is not guaranteed stable across Julia or package versions (see Caveats).

  • JLD2.jl — a widely used HDF5-compatible format with named datasets and better long-term robustness. Recommended when you want to archive data or share files between machines. JLD2 is a separate package you must add with ] add JLD2.

The runnable recipes below use Serialization so they execute with no extra dependency. The JLD2 variants are shown separately and are equivalent in what they store.

julia
using MPSKit, TensorKit
using Serialization

1. Save and reload a finite MPS

serialize writes any object to a file; deserialize reads it back. Here we write to a temporary path and check that the reloaded state is identical by taking the overlap ⟨ψ | ψ_loaded⟩, which is 1 (up to rounding) when the two states coincide.

julia
ψ = FiniteMPS(10, ℂ^2, ℂ^16)

path = tempname()          # a fresh temporary file path
serialize(path, ψ)

ψ_loaded = deserialize(path)
abs(dot(ψ, ψ_loaded))      # ≈ 1: the reloaded state equals the original
1.0000000000000016

The reloaded object is a genuine FiniteMPS, ready for any further computation:

julia
ψ_loaded isa FiniteMPS
true

Nothing here is specific to a random state — the same holds for a state returned by find_groundstate or timestep. Save the state you actually care about the moment you have it.

2. Save and reload an infinite MPS

InfiniteMPS works exactly the same way. Because an infinite state is normalized by its gauge, the overlap check above is not the natural diagnostic; instead compare the gauged tensors directly.

julia
ψ∞ = InfiniteMPS(ℂ^2, ℂ^16)

path∞ = tempname()
serialize(path∞, ψ∞)

ψ∞_loaded = deserialize(path∞)
ψ∞_loaded.AL[1]  ψ∞.AL[1]   # left-gauged tensors match
true

3. Store several objects together

To keep a state alongside metadata (parameters, a description, the energy you measured), serialize a NamedTuple or Dict in one file. This keeps everything that belongs together in a single artifact.

julia
result = (state = ψ, χ = 16, note = "TFIM ground state")

path_result = tempname()
serialize(path_result, result)

back = deserialize(path_result)
back.note
"TFIM ground state"
julia
abs(dot(back.state, ψ))     # the embedded state round-trips too
1.0000000000000016

4. The JLD2 variant

JLD2.jl stores objects under string keys and is the more portable choice for archival data. Add it with ] add JLD2 first. The following is equivalent to the Serialization recipes above; it is not executed here because JLD2 is not a dependency of this documentation build.

julia
using JLD2

# save one or more named objects
jldsave("state.jld2"; ψ, χ = 16, note = "TFIM ground state")

# load them back by name
ψ_loaded = load("state.jld2", "ψ")
note     = load("state.jld2", "note")

Symmetric states round-trip through JLD2 without any extra work: the TensorMaps carry their own symmetry sectors and vector spaces, so a state built on, e.g., Z2Space is restored with its full symmetry structure intact.


Environments

Cached environments (the objects returned by environments, held inside the value from find_groundstate and friends) are serializable in exactly the same way as states — they are also just tensors. In practice, however, it is usually not worth saving them: environments are derived data, tied to one specific state, and recomputing them from a stored state is cheap compared to the optimization that produced the state.

The recommended workflow is therefore to save only the state and rebuild the environments after loading:

julia
using MPSKitModels    # for the Hamiltonian
H = transverse_field_ising(FiniteChain(10))

envs = environments(ψ_loaded, H, ψ_loaded)   # rebuilt from the reloaded state

If you do have a reason to persist environments (e.g. to resume an expensive iterative build), serialize/deserialize them just like a state.

Caveats

  • Version compatibility. Serialization files are not guaranteed to be readable by a different Julia version, nor after MPSKit or TensorKit change their internal type layout. Treat Serialization output as a scratch artifact within one environment; use JLD2 for anything you need to reopen weeks later or on another machine.

  • Symmetric tensors are self-describing. A saved state carries the vector spaces and symmetry sectors of every tensor, so you do not need to record the symmetry separately — loading reconstructs the full space structure. This was verified for a Z2-symmetric state round-tripping through both Serialization and JLD2.

  • File size. A stored state is roughly the size of its tensors, which grows with the bond dimension (and, for symmetric states, the sector structure). For large-bond-dimension states these files can be substantial; write them to scratch/bulk storage rather than a quota-limited home directory, and consider saving only the final state rather than every intermediate.

  • What to save. Prefer saving the state (and the parameters needed to rebuild its Hamiltonian) over saving derived caches like environments. A state plus its model definition is enough to reconstruct everything else.