Side effects of Observer

Suppose I put a measurement in my custom observer to be done at the end of the sweep that alters the orthogonality center of psi. Then the Hamiltonian MPO edge tensors will presumably be out of date and will require recomputation. I assume that the edge tensors are smart enough to figure this out, right? But then you get an unanticipated performance hit. A way around this is to copy psi before you start your custom measurement. Then there is some risk of using up too much memory if psi is ordinarily stored on disk, but usually this would not be an issue and this seems like the best option.

I think it would be undefined behavior to use orthogonalize! inside of an observer (without copying the MPS) and because of how Julia manages memory there would be no way for us to properly handle that and fix the projected MPOs.

However, it seems like a simple fix would be to copy the MPS before calling orthogonalize!, i.e.:

psi = orthogonalize!(copy(psi))

Note that copy(psi) does a shallow copy of psi, so it doesn’t copy all of the tensor data, just the data structure of the MPS. So there shouldn’t be any more memory usage beyond what would be used by orthogonalize! anyway (except a small overhead for copying pointers, which is what Julia does when doing a shallow copy of Vector{ITensor}).

(In principle, we could pass the projected MPOs to the observer as well, and then you could fix the projected MPO yourself from within the observer. But that shouldn’t be necessary with my suggestion above.)

So the shallow copy will make new copies of all the tensors it alters during orthogonalize!, and thus cannot affect the original psi? Then this is a nice way to do it. A typical case where this could come up is in calling correlation_matrix, but it looks like correlation_matrix does a copy(psi) before it starts calling orthogonalize!.

Yeah, othogonalize! won’t do in-place operations on the tensor data of the MPS, it just swaps out the tensors that it orthogonalizes.

I just checked and we already provide a function psi = orthogonalize(psi) which is equivalent to psi = othogonalize!(copy(psi)). We should encourage people to use that since the in-place version doesn’t give any performance benefit and it is harder to reason about (we’re moving towards that style in GitHub - mtfishman/ITensorNetworks.jl: A package with general tools for working with higher-dimensional tensor networks based on ITensor.).