Code to replicate the figures in the corresopnding paper can be found on Github.
Introduction
A quantum system is described by a Hamiltonian matrix H.
When the system is at thermal equilibrium at temperature 1/β, then the state of the system is described by the matrix
ρ=exp(−βH)/Z(β),Z(β)=tr(exp(−βH)).
The function Z(β) is called the partition function, and gives us access to all kinds of thermodynamic quantities such as the energy, specific heat, magnetization, etc.
Often we are interested in the state of some subsystem of the total system.
This is represented by
ρ∗(β)=trb(−βH)/Z(β),
where trb(⋅) is the partial trace described below.
Exponentially big linear algebra
Computing the trace (and partial trace) of a given matrix is trivial. For the trace you just sum the diagonal entries, and for the partial trace you do something similarly easily.
However, we are starting with H not exp(−βH), and this presents some issues.
For a system with N sites, the size of H is 2N.
This means that even for reasonably small N, storing a N×N matrix is impossible.
For instance, if N=20, then 2N is about one million, and storing a N×N matrix of double precision floating point numbers (64 bits per number) would require over 8 terrabtyes of memory!
Increasing N by one quadruples the memory costs, so even if we have 8 terrabytes of memory, we’ll quickly run out for N even just a bit larger.
Fortunately, H typically has a very sparse representation, often with just O(N) nonzero entries.
While this means we can store H itself, exp(−βH) is typically not sparse and therefore it is intractable to store.
Moreover, even if we would store exp(−βH), computing it would be a big task!
Stochastic trace estimation
There are lots of algorithms for estimating vTf(H)v using only matrix-vector products with H.
For instance, the Lanczos method for matrix function approximation (Lanczos-FA) is a common choice.
There are lots of nice overviews on stochastic trace estimation, and this blog post by Ethan Epperly is especially good.
For our purposes, we only need to know that if v is a vector for which E[vvT]=I (i.e. all the entries are uncorrelated), then
E[vTAv]=tr(A).
A simple way to generate such a v is by taking each entry to be an independent standard normal random variable.
We will call estimators of the form vTAv a quadratic trace estimator.
Partial trace estimation
Suppose we can partition a matrix A as
A=A1,1A2,1⋮Ada,1A1,2A2,2⋮Ada,2⋯⋯⋱⋯A1,daA2,da⋮Ada,da.
Then the partial trace of A is defined as
trb(A):=tr(A1,1)tr(A2,1)⋮tr(Ada,1)tr(A1,2)tr(A2,2)⋮tr(Ada,2)⋯⋯⋱⋯tr(A1,da)tr(A2,da)⋮tr(Ada,da).
Note that each entry of the partial trace is obtained by taking the trace of a certain matrix.
This suggests we can apply use quadratic trace estimators to approximate each of the entries of the partial trace!
Indeed,
(Ida⊗v)TA(Ida⊗v)=vTA1,1vvTA2,1v⋮vTAda,1vvTA1,2vvTA2,2v⋮vTAda,2v⋯⋯⋱⋯vTA1,davvTA2,dav⋮vTAda,dav
provides an unbiased estimator for trb(A).
Given independent and identically distributed copies v1,…,vm of v, we arrive at an estimator
trbm(A):=m1i=1∑m(Ida⊗vi)TA(Ida⊗vi).