# Various questions about QN conservation in Julia

+1 vote
retagged

I think I get the gist of how QN conservation works in ITensors.jl, but now that I want to try doing more complicated things, I want to make sure I really understand it properly. To that end, I had a few questions.

(1) Do the quantum numbers have to be integers? If so, is there a fundamental reason for forcing them to be this way in the code?

(2) Here is code taken from the spinone.jl file. Other examples will have similar things:

if conserve_sz
up = QN("Sz",+2) => 1
z0 = QN("Sz", 0) => 1
dn = QN("Sz",-2) => 1
return [Index(up,z0,dn;tags="Site,S=1,n=\$n") for n=1:N]
end


What does the "=> 1" mean here, and why are all three of up, z0, dn being mapped to 1?

(3) Can the code handle arbitrarily many conserved QNs at once? If so, would it be possible/feasible to implement local gauge symmetries (such as the Gauss's Law constraint on the lattice formulation of the Schwinger model, which was mentioned in another question) using conserved QNs?

(4) My understanding is that, if you are conserving some QN, each term in an MPO that you create has to have a definite QN flux--for instance, if you are conserving total Sz, then you need to use S+ and S- operators instead of Sx and Sy operators. However, in an MPO I constructed for the Hamiltonian of the lattice Schwinger model, even though I am pretty sure I only used allowed operators, I got a different error saying:

LoadError: No block found with QN equal to QN(("Sz",-4))


I can post some code, but it would be a bit long, and I'm not sure how helpful it would be. For context, the lattice has alternating spin-1/2 sites (for the fermions and antifermions) and spin-1 sites (for the links, which I am truncating at 1 for now, which is why I can describe them as spin-1 sites). My best guess at what is going on here is that there is a term in the Hamiltonian that, when applied to a state, changes the total Sz by -4. But why is this an issue? Does this mean that every term in the MPO must not change the total Sz? If not, then what is the relevant constraint?

I tried to look at some of the other source files to understand these things better, but I wasn't getting any clarity. Any help on this would be greatly appreciated.

+1 vote

Hi Sujay,
Thanks for the good & detailed questions. These touch on things we want everyone to understand when working in a more hands-on way with the QN conserving ITensor system. We're trying to find the best way to document and introduce them, and one way is just by building a knowledge base on this forum. As you probably know, the draft of the ITensor Book on the website also introduces some QN ITensor concepts: http://itensor.org/docs.cgi?vers=julia&page=book . And we will soon publish an ITensor paper that provides many details.

(1) yes we require the quantum numbers to be integers for reasons of efficiency and correctness. E.g. we wouldn't want to store them as floating point because that would introduce all sorts of complications. But your question (which others have asked before) does remind me that Julia has facilities for exact computations with rational numbers, which we might consider expanding QN's to use in the future. For now please just make an integer correspondence between the quantum numbers as used on paper and in ITensor (e.g. we have the convention of working in units of 1/2 for spin quantum numbers, so 1/2 becomes 1, 1 becomes 2, etc.).

(2) The notation A => B in Julia creates a Pair(A,B) object, which is just a struct holding the values A and B. It can be an unfamiliar notation coming from other languages, and it was for me too. So it is nothing specific to ITensor but just a convenient way to group two values together that we've adopted for this Index constructor. Each pair denotes a subspace of the Index, meaning that the entire index labels the basis of a vector space (of dimension 3 here) and each subspace occurs sequentially giving the space a direct-sum structure. The second number of each pair is the dimension of that subspace. So the 1's are saying that each subspace is of dimension 1.

(3) I'm not sure exactly in what sense you're asking about having an arbitrary number of QNs at once, but I can comment on a few relevant things here. One is that an Index can have as many QN subspaces as you want. So in code like:

i = Index(QN(0)=>1, QN(1)=>2, Q(2)=4, ... )


the list of QN=>Int pairs can go on as long as you want, up to the memory limits of the machine. On the other hand, within a QN object itself, you can only have up to 4 different types of quantum numbers stored. So like QN(("A",1),("B",0),("C",-1),("D",3)) would be reaching the limit of 4 different QN values. This is for reasons of efficiency as it greatly reduces allocations while on the other hand we've so far heard of few cases where more than 4 QN names were needed at once. But if you definitely do need more, we can work with you to lift this restriction.

I don't know much about the Schwinger model or its symmetries. Could you provide more information about how you're thinking of implementing it and the Hamiltonian used? Our ITensor QN system is currently only designed to handle the case of global, Abelian symmetries of a Hamiltonian. So it does not handle non-Abelian symmetries such as global SU(2) for example. But local symmetries such as in lattice gauge theories are an interesting case I think we've just not thought about. So it's not obvious to me whether our existing system can handle that case, or whether it could with some small changes, or even what is the right approach to such symmetries in tensor networks more broadly. This review could provide some information about the status of this topic: https://arxiv.org/abs/1810.12838

(4) Regarding the construction of QN-conserving MPOs, some of the precise details can get rather involved and at the same time many are just conventions and could vary from one implementation to another. The conventions we use in ITensor code are that for a QN-conserving MPO with total flux zero (such as the Hamiltonian, which by definition has to be total flux zero since it preserves the quantum numbers), all of the MPO tensors are themselves individually flux zero. This isn't formally necessary, but is a very natural and convenient convention. So when constructing each tensor, flux non-zero operators such as S+ or S- are "balanced" by bond or link indices of the MPO having subspaces which cancel out the flux of the operator to keep things net flux zero.

I gave a pretty detailed answer about some of these conventions in this forum question:
http://itensor.org/support/2083/properly-handle-quantum-number-for-system-spin-half-moments?show=2083#q2083

Please take a look at that, even though the question is about a C++ code file that makes the Heisenberg MPO. Both my answer there as well as the C++ example itself could be helpful. If you'd like to discuss how some of that C++ code would be adapted to the Julia version we could discuss that in the future.

Ok hope all of that helps you to make some more progress - I understand it's a lot to digest.

Best regards,
Miles