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.
using MPSKit, TensorKit
using Serialization1. 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.
ψ = 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 original1.0000000000000016The reloaded object is a genuine FiniteMPS, ready for any further computation:
ψ_loaded isa FiniteMPStrueNothing 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.
ψ∞ = InfiniteMPS(ℂ^2, ℂ^16)
path∞ = tempname()
serialize(path∞, ψ∞)
ψ∞_loaded = deserialize(path∞)
ψ∞_loaded.AL[1] ≈ ψ∞.AL[1] # left-gauged tensors matchtrue3. 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.
result = (state = ψ, χ = 16, note = "TFIM ground state")
path_result = tempname()
serialize(path_result, result)
back = deserialize(path_result)
back.note"TFIM ground state"abs(dot(back.state, ψ)) # the embedded state round-trips too1.00000000000000164. 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.
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:
using MPSKitModels # for the Hamiltonian
H = transverse_field_ising(FiniteChain(10))
envs = environments(ψ_loaded, H, ψ_loaded) # rebuilt from the reloaded stateIf 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.
Serializationfiles are not guaranteed to be readable by a different Julia version, nor after MPSKit or TensorKit change their internal type layout. TreatSerializationoutput 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 bothSerializationand 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.