Fermions and the Jordan-Wigner transformation

The Jordan-Wigner tranformation maps fermionic creation- and annihilation operators to (bosonic) spin-operators.

Spinless fermions in 1D

Let’s start by explicitly writing down the transformation. With the Pauli matrices \(\sigma^{x,y,z}_j\) and \(\sigma^{\pm}_j = (\sigma^x_j \pm \mathrm{i} \sigma^y_j)/2\) on each site, we can map

\[\begin{split}n_j &\leftrightarrow (\sigma^{z}_j + 1)/2 \\ c_j &\leftrightarrow (-1)^{\sum_{l < j} n_l} \sigma^{-}_j \\ c_j^\dagger &\leftrightarrow (-1)^{\sum_{l < j} n_l} \sigma^{+}_j\end{split}\]

The \(n_l\) in the second and third row are defined in terms of Pauli matrices according to the first row. We do not interpret the Pauli matrices as spin-1/2; they have nothing to do with the spin in the spin-full case. If you really want to interpret them physically, you might better think of them as hard-core bosons (\(b_j =\sigma^{-}_j, b^\dagger_j=\sigma^{+}_j\)), with a spin of the fermions mapping to a spin of the hard-core bosons.

Note that this transformation maps the fermionic operators \(c_j\) and \(c^\dagger_j\) to global operators; although they carry an index j indicating a site, they actually act on all sites l <= j! Thus, clearly the operators C and Cd defined in the FermionSite do not directly correspond to \(c_j\) and \(c^\dagger_j\). The part \((-1)^{\sum_{l < j} n_l}\) is called Jordan-Wigner string and in the FermionSite is given by the local operator \(JW := (-1)^{n_l}\) acting all sites l < j. Since this important, let me stress it again:


The fermionic operator \(c_j\) (and similar \(c^\dagger_j\)) maps to a global operator consisting of the Jordan-Wigner string built by the local operator JW on sites l < j and the local operator C (or Cd, respectively) on site j.

On the sites itself, the onsite operators C and Cd in the FermionSite fulfill the correct anti-commutation relation, without the need to include JW strings. The JW string is necessary to ensure the anti-commutation for operators acting on different sites.

Written in terms of onsite operators defined in the FermionSite, with the i-th entry entry in the list acting on site i, the relations are thus:

["JW", ..., "JW", "C",  "Id", ..., "Id"]   # for the annihilation operator
["JW", ..., "JW", "Cd", "Id", ..., "Id"]   # for the creation operator

Note that "JW" squares to the identity, "JW JW" == "Id", which is the reason that the Jordan-wigner string completely cancels in \(n_j = c^\dagger_j c_j\). In the above notation, this can be written as:

["JW", ..., "JW", "Cd",  "Id", ..., "Id"] * ["JW", ..., "JW", "C", "Id", ..., "Id"]
== ["JW JW", ..., "JW JW", "Cd C",  "Id Id", ..., "Id Id"]      # by definition of the tensorproduct
== ["Id",    ..., "Id",    "N",     "Id",    ..., "Id"]         # by definition of the local operators
# ("X Y" stands for the local operators X and Y applied on the same site. We assume that the "Cd" and "C" on the first line act on the same site.)

For a pair of operators acting on different sites, JW strings have to be included for every site between the operators. For example, taking i < j, \(c^\dagger_i c_j \leftrightarrow \sigma_i^{+} (-1)^{\sum_{i <=l < j} n_l} \sigma_j^{-}\). More explicitly, for j = i+2 we get:

["JW", ..., "JW", "Cd", "Id", "Id", "Id", ..., "Id"] * ["JW", ..., "JW", "JW", "JW", "C", "Id", ..., "Id"]
== ["JW JW", ..., "JW JW", "Cd JW",  "Id JW", "Id C", ..., "Id"]
== ["Id",    ..., "Id",    "Cd JW",  "JW",    "C",    ..., "Id"]

In other words, the Jordan-Wigner string appears only in the range i <= l < j, i.e. between the two sites and on the smaller/left one of them. (You can easily generalize this rule to cases with more than two \(c\) or \(c^\dagger\).)

This last line (as well as the last line of the previous example) can be rewritten by changing the order of the operators Cd JW to "JW Cd" == - "Cd". (This is valid because either site i is occupied, yielding a minus sign from the JW, or it is empty, yielding a 0 from the Cd.)

This is also the case for j < i, say j = i-2: \(c^\dagger_i c_j \leftrightarrow (-1)^{\sum_{j <=l < i} n_l} \sigma_i^{+} \sigma_j^{-}\). As shown in the following, the JW again appears on the left site, but this time acting after C:

["JW", ..., "JW", "JW", "JW", "Cd", "Id", ..., "Id"] * ["JW", ..., "JW", "C", "Id", "Id", "Id", ..., "Id"]
== ["JW JW", ..., "JW JW", "JW C",  "JW", "Cd Id", ..., "Id"]
== ["Id",    ..., "Id",    "JW C",  "JW", "Cd",    ..., "Id"]

Higher dimensions

For an MPO or MPS, you always have to define an ordering of all your sites. This ordering effectifely maps the higher-dimensional lattice to a 1D chain, usually at the expence of long-range hopping/interactions. With this mapping, the Jordan-Wigner transformation generalizes to higher dimensions in a straight-forward way.

Spinful fermions


As illustrated in the above picture, you can think of spin-1/2 fermions on a chain as spinless fermions living on a ladder (and analogous mappings for higher dimensional lattices). Each rung (a blue box in the picture) forms a SpinHalfFermionSite which is composed of two FermionSite (the circles in the picture) for spin-up and spin-down. The mapping of the spin-1/2 fermions onto the ladder induces an ordering of the spins, as the final result must again be a one-dimensional chain, now containing both spin species. The solid line indicates the convention for the ordering, the dashed lines indicate spin-preserving hopping \(c^\dagger_{s,i} c_{s,i+1} + h.c.\) and visualize the ladder structure. More generally, each species of fermions appearing in your model gets a separate label, and its Jordan-Wigner string includes the signs \((-1)^{n_l}\) of all species of fermions to the ‘left’ of it (in the sense of the ordering indicated by the solid line in the picture).

In the case of spin-1/2 fermions labeled by \(\uparrow\) and \(\downarrow\) on each site, the complete mapping is given (where j and l are indices of the FermionSite):

\[\begin{split}n_{\uparrow,j} &\leftrightarrow (\sigma^{z}_{\uparrow,j} + 1)/2 \\ n_{\downarrow,j} &\leftrightarrow (\sigma^{z}_{\downarrow,j} + 1)/2 \\ c_{\uparrow,j} &\leftrightarrow (-1)^{\sum_{l < j} n_{\uparrow,l} + n_{\downarrow,l}} \sigma^{-}_{\uparrow,j} \\ c^\dagger_{\uparrow,j} &\leftrightarrow (-1)^{\sum_{l < j} n_{\uparrow,l} + n_{\downarrow,l}} \sigma^{+}_{\uparrow,j} \\ c_{\downarrow,j} &\leftrightarrow (-1)^{\sum_{l < j} n_{\uparrow,l} + n_{\downarrow,l}} (-1)^{n_{\uparrow,j}} \sigma^{-}_{\downarrow,j} \\ c^\dagger_{\downarrow,j} &\leftrightarrow (-1)^{\sum_{l < j} n_{\uparrow,l} + n_{\downarrow,l}} (-1)^{n_{\uparrow,j}} \sigma^{+}_{\downarrow,j} \\\end{split}\]

In each of the above mappings the operators on the right hand sides commute; we can rewrite \((-1)^{\sum_{l < j} n_{\uparrow,l} + n_{\downarrow,l}} = \prod_{l < j} (-1)^{n_{\uparrow,l}} (-1)^{n_{\downarrow,l}}\), which resembles the actual structure in the code more closely. The parts of the operator acting in the same box of the picture, i.e. which have the same index j or l, are the ‘onsite’ operators in the SpinHalfFermionSite: for example JW on site j is given by \((-1)^{n_{\uparrow,j}} (-1)^{n_{\downarrow,j}}\), Cu is just the \(\sigma^{-}_{\uparrow,j}\), Cdu is \(\sigma^{+}_{\uparrow,j}\), Cd is \((-1)^{n_{\uparrow,j}} \sigma^{-}_{\downarrow,j}\). and Cdd is \((-1)^{n_{\uparrow,j}} \sigma^{+}_{\downarrow,j}\). Note the asymmetry regarding the spin in the definition of the onsite operators: the spin-down operators include Jordan-Wigner signs for the spin-up fermions on the same site. This asymetry stems from the ordering convention introduced by the solid line in the picture, according to which the spin-up site is “left” of the spin-down site. With the above definition, the operators within the same SpinHalfFermionSite fulfill the expected commutation relations, for example "Cu Cdd" == - "Cdd Cu", but again the JW on sites left of the operator pair is crucial to get the correct commutation relations globally.


Again, the fermionic operators \(c_{\downarrow,j}, c^\dagger_{\downarrow,j}, c_{\downarrow,j}, c^\dagger_{\downarrow,j}\) correspond to global operators consisting of the Jordan-Wigner string built by the local operator JW on sites l < j and the local operators 'Cu', 'Cdu', 'Cd', 'Cdd' on site j.

Written explicitly in terms of onsite operators defined in the FermionSite, with the j-th entry entry in the list acting on site j, the relations are:

["JW", ..., "JW", "Cu",  "Id", ..., "Id"]    # for the annihilation operator spin-up
["JW", ..., "JW", "Cd",  "Id", ..., "Id"]    # for the annihilation operator spin-down
["JW", ..., "JW", "Cdu",  "Id", ..., "Id"]   # for the creation operator spin-up
["JW", ..., "JW", "Cdd",  "Id", ..., "Id"]   # for the creation operator spin-down

As you can see, the asymmetry regaring the spins in the definition of the local onsite operators "Cu", "Cd", "Cdu", "Cdd" lead to a symmetric definition in the global sense. If you look at the definitions very closely, you can see that in terms like ["Id", "Cd JW", "JW", "Cd"] the Jordan-Wigner sign \((-1)^{n_\uparrow,2}\) appears twice (namely once in the definition of "Cd" and once in the "JW" on site 2) and could in principle be canceled, however in favor of a simplified handling in the code we do not recommend you to cancel it. Similar, within a spinless FermionSite, one can simplify "Cd JW" == "Cd" and "JW C" == "C", but these relations do not hold in the SpinHalfSite, and for consistency we recommend to explicitly keep the "JW" operator string even in nearest-neighbor models where it is not strictly necessary.

How to handle Jordan-Wigner strings in practice

There are only a few pitfalls where you have to keep the mapping in mind: When building a model, you map the physical fermionic operators to the usual spin/bosonic operators. The algorithms don’t care about the mapping, they just use the given Hamiltonian, be it given as MPO for DMRG or as nearest neighbor couplings for TEBD. Only when you do a measurement (e.g. by calculating an expectation value or a correlation function), you have to reverse this mapping. Be aware that in certain cases, e.g. when calculating the entanglement entropy on a certain bond, you cannot reverse this mapping (in a straightforward way), and thus your results might depend on how you defined the Jordan-Wigner string.

Whatever you do, you should first think about if (and how much of) the Jordan-Wigner string cancels. For example for many of the onsite operators (like the particle number operator N or the spin operators in the SpinHalfFermionSite) the Jordan-Wigner string cancels completely and you can just ignore it both in onsite-terms and couplings. To check, whether the Jordan-Wigner string cancels for a given operator, take a look at need_JW_string and op_needs_JW(). In case of operators acting on different sites, you typically have a Jordan-Wigner string inbetween (e.g. for the \(c^\dagger_i c_j\) examples described above and below) or no Jordan-Wigner strings at all (e.g. for density-density interactions \(n_i n_j\)). In fact, the case that the Jordan Wigner string on the left of the first non-trivial operator does not cancel is currently not supported for models and expectation values, as it usually doesn’t appear in practice.

When building a model with the CouplingModel, onsite terms for which the Jordan-Wigner string cancels can be added directly. Care has to be taken when adding couplings with add_coupling(). When you need a Jordan-Wigner string inbetween the operators, set the optional arguments op_string='JW', str_on_first=True. Then, the function automatically takes care of the Jordan-Wigner string in the correct way, adding it on the left operator. With the default arguments, it is checked automatically whether the model

Obviously, you should be careful about the convention which of the two coupling terms is applied first (in a physical sense as an operator acting on a state), as this corresponds to a sign. We follow the convention that the operator given as argument op2 is applied first, independent of wheter it ends up left or right in the MPS ordering sense.

As a concrete example, let us specify a hopping \(\sum_{\langle i, j\rangle} (c^\dagger_i c_j + h.c.) = \sum_{\langle i, j\rangle} (c^\dagger_i c_j + c^\dagger_j c_i)\) in a 1D chain of FermionSite with add_coupling():

add_coupling(strength, 0, 'Cd', 0, 'C', 1, 'JW', True)
add_coupling(strength, 0, 'Cd', 0, 'C', -1, 'JW', True)
# (without the last 2 arguments, add_coupling checks for necessary JW strings automatically)

Slightly more complicated, to specify the hopping \(\sum_{\langle i, j\rangle, s} (c^\dagger_{s,i} c_{s,j} + h.c.)\) in the Fermi-Hubbard model on a 2D square lattice, we would need more terms:

for (dx, dy) in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
    add_coupling(strength, 0, 'Cdu', 0, 'Cu', (dx, dy), 'JW', True)
    add_coupling(strength, 0, 'Cdd', 0, 'Cd', (dx, dy), 'JW', True)

If you want to build a model directly as an MPO or with nearest-neighbor bonds only, you have to care about how to handle the Jordan-Wigner string correctly.

The most important functions for doing measurements are probably expectation_value() and correlation_function(). Again, if all the Jordan-Wigner strings cancel, you don’t have to worry about them at all, e.g. for many onsite operators or correlation functions involving only number operators. If you measure operators involving multiple sites with expectation_value, take care to include the Jordan-Wigner string correctly while building these operators.

The correlation_function() supports a Jordan-Wigner string in between the two operators to be measured. As for add_coupling(), you should set the optional arguments op_string='JW', str_on_first=True in that case. Functions like expectation_value_term() also care about the Jordan Wigner string (if specified in the documentation).