Skip to content

Measurements

Measurements in the form of expectation values of wavefunctions, $$ \langle \mathcal{O}\rangle = \langle \psi | \mathcal{O} | \psi \rangle,$$ can be evaluated using the inner function. For example, we compute a static spin correlation \(\langle S_{0}^{z} S_{j}^{z}\rangle\) between site \(0\) (resp. \(1\) in Julia) and \(j\).

for i in 1:N
    op = Op("SzSz", [1, i])
    corr = inner(op, psi0)
end
for (int i=0; i<N; ++i) {
  auto op = Op("SzSz", {0, i});
  double corr = inner(op, psi0);
}

Notice, that in Julia sites start counting from \(1\), whereas in C++ sites are counted from \(0\). Furthermore, if a complex wave function or operator is involved, the function innerC in C++ should be called, which returns a complex number. In Julia only inner is available whose return type is decided at runtime.

Correlation functions

The operator algebra introduced earlier makes it straightforward to measure arbitrary correlation functions. Since operators can be multiplied, we can build any composite operator on the fly and hand it to inner. For instance, the mixed spin correlation \(\langle S^x_0 S^y_1 \rangle\) is obtained by multiplying the two single-site operators and measuring the resulting product.

# Build an arbitrary composite operator via the algebra product, e.g. S^x_0 S^y_1
op = Op("Sx", 1) * Op("Sy", 2)
corr = inner(op, psi0)
// Build an arbitrary composite operator via the algebra product, e.g. S^x_0 S^y_1
auto op = Op("Sx", 0) * Op("Sy", 1);
complex corr = innerC(op, psi0);

This works for products on any number of sites and for any combination of operator types, allowing generic multi-point correlators to be assembled from elementary Op objects. Note that such correlators are frequently complex, so the innerC function is used in the C++ version.

Local expectation values

A common task is to evaluate the expectation value of a single-site operator on every site of the lattice at once, for example the local magnetization \(\langle S_i^z \rangle\) or the local density \(\langle n_i \rangle\). This is conveniently done with the expect function, which takes the state and the type of a single-site operator and returns a vector whose \(i\)-th entry is \(\langle \psi | \mathcal{O}_i | \psi \rangle\).

# <psi0| Sz_i |psi0> on every site i, returned as a vector
sz = expect(psi0, "Sz")
// <psi0| Sz_i |psi0> on every site i, returned as a vector
arma::vec sz = expect(psi0, "Sz");

Correlation matrices

Similarly, the two-point correlations of a pair of single-site operators between all pairs of sites can be computed in one call with the correlation_matrix function. Given two operator types, it returns the matrix $$ C_{ij} = \langle \psi | \mathcal{O}^{(1)}_i \, \mathcal{O}^{(2)}_j | \psi \rangle. $$

# C(i, j) = <psi0| Sz_i Sz_j |psi0> for all pairs of sites
szsz = correlation_matrix(psi0, "Sz", "Sz")
// C(i, j) = <psi0| Sz_i Sz_j |psi0> for all pairs of sites
arma::mat szsz = correlation_matrix(psi0, "Sz", "Sz");

For instance, choosing the operator types "Adag" and "A" yields the single-particle density matrix. On a symmetry-adapted block, the operator is automatically symmetrized so that it acts within the block.

A few points are worth keeping in mind when using expect and correlation_matrix:

  • The state is assumed to be normalized; the raw matrix elements are returned without dividing by \(\langle \psi | \psi \rangle\).
  • The operator (or the product of operators) must keep the state within its block. An operator that changes a conserved quantum number would make the expectation value vanish by symmetry and is instead reported as a block mismatch.
  • Both functions return a real result and raise an error if the result is complex. In that case, the complex-valued variants expectC and correlation_matrixC should be used in C++. In Julia, expect and correlation_matrix return a real or complex result as appropriate.