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
J!_ejE{{T3R?di
diff --git a/docs/src/examples/DMRG.md b/docs/src/examples/DMRG.md
deleted file mode 100644
index 48d51feb11..0000000000
--- a/docs/src/examples/DMRG.md
+++ /dev/null
@@ -1,552 +0,0 @@
-# DMRG Code Examples
-
-## Perform a basic DMRG calculation
-
-Because tensor indices in ITensor have unique identities, before we can make a Hamiltonian
-or a wavefunction we need to construct a "site set" which will hold the site indices defining
-the physical Hilbert space:
-
-```julia
-using ITensors, ITensorMPS
-N = 100
-sites = siteinds("S=1",N)
-```
-
-Here we have chosen to create a Hilbert space of N spin 1 sites. The string "S=1"
-denotes a special Index tag which hooks into a system that knows "S=1" indices have
-a dimension of 3 and how to create common physics operators like "Sz" for them.
-
-Next we'll make our Hamiltonian matrix product operator (MPO). A very
-convenient way to do this is to use the OpSum helper type which lets
-us input a Hamiltonian (or any sum of local operators) in similar notation
-to pencil-and-paper notation:
-
-```julia
-os = OpSum()
-for j=1:N-1
- os += 0.5,"S+",j,"S-",j+1
- os += 0.5,"S-",j,"S+",j+1
- os += "Sz",j,"Sz",j+1
-end
-H = MPO(os,sites)
-```
-
-In the last line above we convert the OpSum helper object to an actual MPO.
-
-Before beginning the calculation, we need to specify how many DMRG sweeps to do and
-what schedule we would like for the parameters controlling the accuracy.
-These parameters can be specified as follows:
-
-```julia
-nsweeps = 5 # number of sweeps is 5
-maxdim = [10,20,100,100,200] # gradually increase states kept
-cutoff = [1E-10] # desired truncation error
-```
-
-The random starting wavefunction `psi0` must be defined in the same Hilbert space
-as the Hamiltonian, so we construct it using the same collection of site indices:
-
-```julia
-psi0 = random_mps(sites;linkdims=2)
-```
-
-Here we have made a random MPS of bond dimension 2. We could have used a random product
-state instead, but choosing a slightly larger bond dimension can help DMRG avoid getting
-stuck in local minima. We could also set psi to some specific initial state using the
-`MPS` constructor, which is actually required if we were conserving QNs.
-
-Finally, we are ready to call DMRG:
-
-```julia
-energy,psi = dmrg(H,psi0;nsweeps,maxdim,cutoff)
-```
-
-When the algorithm is done, it returns the ground state energy as the variable `energy` and an MPS
-approximation to the ground state as the variable `psi`.
-
-Below you can find a complete working code that includes all of these steps:
-
-```julia
-using ITensors, ITensorMPS
-
-let
- N = 100
- sites = siteinds("S=1",N)
-
- os = OpSum()
- for j=1:N-1
- os += 0.5,"S+",j,"S-",j+1
- os += 0.5,"S-",j,"S+",j+1
- os += "Sz",j,"Sz",j+1
- end
- H = MPO(os,sites)
-
- nsweeps = 5 # number of sweeps is 5
- maxdim = [10,20,100,100,200] # gradually increase states kept
- cutoff = [1E-10] # desired truncation error
-
- psi0 = random_mps(sites;linkdims=2)
-
- energy,psi = dmrg(H,psi0;nsweeps,maxdim,cutoff)
-
- return
-end
-```
-
-## Using a Custom Observer for DMRG
-
-An Observer is any object which can be used to perform custom measurements throughout
-a DMRG calculation and to stop a DMRG calculation early. Because an Observer has
-access to the entire wavefunction at every step, a wide range of customization is
-possible.
-
-For detailed examples of making custom Observers, see the [Observer](@ref observer)
-section of the documentation.
-
-
-## DMRG Calculation with Mixed Local Hilbert Space Types
-
-The following fully-working example shows how to set up a calculation
-mixing S=1/2 and S=1 spins on every other site of a 1D system. The
-Hamiltonian involves Heisenberg spin interactions with adjustable
-couplings between sites of the same spin or different spin.
-
-Note that the only difference from a regular ITensor DMRG calculation
-is that the `sites` array has Index objects which alternate in dimension
-and in which physical tag type they carry, whether `"S=1/2"` or `"S=1"`.
-(Try printing out the sites array to see!)
-These tags tell the OpSum system which local operators to use for these
-sites when building the Hamiltonian MPO.
-
-```julia
-using ITensors, ITensorMPS
-
-let
- N = 100
-
- # Make an array of N Index objects with alternating
- # "S=1/2" and "S=1" tags on odd versus even sites
- # (The first argument n->isodd(n) ... is an
- # on-the-fly function mapping integers to strings)
- sites = siteinds(n->isodd(n) ? "S=1/2" : "S=1",N)
-
- # Couplings between spin-half and
- # spin-one sites:
- Jho = 1.0 # half-one coupling
- Jhh = 0.5 # half-half coupling
- Joo = 0.5 # one-one coupling
-
- os = OpSum()
- for j=1:N-1
- os += 0.5*Jho,"S+",j,"S-",j+1
- os += 0.5*Jho,"S-",j,"S+",j+1
- os += Jho,"Sz",j,"Sz",j+1
- end
- for j=1:2:N-2
- os += 0.5*Jhh,"S+",j,"S-",j+2
- os += 0.5*Jhh,"S-",j,"S+",j+2
- os += Jhh,"Sz",j,"Sz",j+2
- end
- for j=2:2:N-2
- os += 0.5*Joo,"S+",j,"S-",j+2
- os += 0.5*Joo,"S-",j,"S+",j+2
- os += Joo,"Sz",j,"Sz",j+2
- end
- H = MPO(os,sites)
-
- nsweeps = 10
- maxdim = [10,10,20,40,80,100,140,180,200]
- cutoff = [1E-8]
-
- psi0 = random_mps(sites;linkdims=4)
-
- energy,psi = dmrg(H,psi0;nsweeps,maxdim,cutoff)
-
- return
-end
-```
-
-## Use a Sum of MPOs in DMRG
-
-One version of the ITensor `dmrg` function accepts an array of MPOs
-`[H1,H2,H3]` (or any number of MPOs you want). This version of DMRG
-will find the ground state of `H1+H2+H3`. Internally it does not
-actually sum these MPOs, but loops over them during each step of
-the "eigensolver" at the core of the DMRG algorithm, so it is usually
-more efficient than if the MPOs had been summed together into a single MPO.
-
-To use this version of DMRG, say you have MPOs `H1`, `H2`, and `H3`.
-Then call DMRG like this:
-```julia
-energy,psi = dmrg([H1,H2,H3],psi0;nsweeps,maxdim,cutoff)
-```
-
-## Make a 2D Hamiltonian for DMRG
-
-You can use the OpSum system to make 2D Hamiltonians
-much in the same way you make 1D Hamiltonians: by looping over
-all of the bonds and adding the interactions on these bonds to
-the OpSum.
-
-To help with the logic of 2D lattices, ITensor pre-defines
-some helper functions which
-return an array of bonds. Each bond object has an
-"s1" field and an "s2" field which are the integers numbering
-the two sites the bond connects.
-(You can view the source for these functions at [this link](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/ITensorMPS/src/lattices/lattices.jl).)
-
-The two provided functions currently are `square_lattice` and
-`triangular_lattice`. It is not hard to write your own similar lattice
-functions as all they have to do is define an array of `ITensors.LatticeBond`
-structs or even a custom struct type you wish to define. We welcome any
-user contributions of other lattices that ITensor does not currently offer.
-
-Each lattice function takes an optional named argument
-"yperiodic" which lets you request that the lattice should
-have periodic boundary conditions around the y direction, making
-the geometry a cylinder.
-
-**Full example code:**
-
-```julia
-using ITensors, ITensorMPS
-
-let
- Ny = 6
- Nx = 12
-
- N = Nx*Ny
-
- sites = siteinds("S=1/2", N;
- conserve_qns = true)
-
- # Obtain an array of LatticeBond structs
- # which define nearest-neighbor site pairs
- # on the 2D square lattice (wrapped on a cylinder)
- lattice = square_lattice(Nx, Ny; yperiodic = false)
-
- # Define the Heisenberg spin Hamiltonian on this lattice
- os = OpSum()
- for b in lattice
- os += 0.5, "S+", b.s1, "S-", b.s2
- os += 0.5, "S-", b.s1, "S+", b.s2
- os += "Sz", b.s1, "Sz", b.s2
- end
- H = MPO(os,sites)
-
- state = [isodd(n) ? "Up" : "Dn" for n=1:N]
- # Initialize wavefunction to a random MPS
- # of bond-dimension 10 with same quantum
- # numbers as `state`
- psi0 = random_mps(sites,state;linkdims=20)
-
- nsweeps = 10
- maxdim = [20,60,100,100,200,400,800]
- cutoff = [1E-8]
-
- energy,psi = dmrg(H,psi0;nsweeps,maxdim,cutoff)
-
- return
-end
-```
-
-## Compute excited states with DMRG
-
-ITensor DMRG accepts additional MPS wavefunctions as a optional, extra argument.
-These additional 'penalty states' are provided as an array of MPS just
-after the Hamiltonian, like this:
-
-```julia
-energy,psi3 = dmrg(H,[psi0,psi1,psi2],psi3_init;nsweeps,maxdim,cutoff)
-```
-
-Here the penalty states are `[psi0,psi1,psi2]`.
-When these are provided, the DMRG code minimizes the
-energy of the current MPS while also reducing its overlap
-(inner product) with the previously provided MPS. If these overlaps become sufficiently small,
-then the computed MPS is an excited state. So by finding the ground
-state, then providing it to DMRG as a "penalty state" or previous state
-one can compute the first excited state. Then providing both of these, one can
-get the second excited state, etc.
-
-A keyword argument called `weight` can also be provided to
-the `dmrg` function when penalizing overlaps to previous states. The
-`weight` parameter is multiplied by the overlap with the previous states,
-so sets the size of the penalty. It should be chosen at least as large
-as the (estimated) gap between the ground and first excited states.
-Otherwise the optimal value of the weight parameter is not so obvious,
-and it is best to try various weights during initial test calculations.
-
-Note that when the system has conserved quantum numbers, a superior way
-to find excited states can be to find ground states of quantum number (or symmetry)
-sectors other than the one containing the absolute ground state. In that
-context, the penalty method used below is a way to find higher excited states
-within the same quantum number sector.
-
-**Full Example code:**
-
-```julia
-using ITensors, ITensorMPS
-
-let
- N = 20
-
- sites = siteinds("S=1/2",N)
-
- h = 4.0
-
- weight = 20*h # use a large weight
- # since gap is expected to be large
-
-
- #
- # Use the OpSum feature to create the
- # transverse field Ising model
- #
- # Factors of 4 and 2 are to rescale
- # spin operators into Pauli matrices
- #
- os = OpSum()
- for j=1:N-1
- os -= 4,"Sz",j,"Sz",j+1
- end
- for j=1:N
- os -= 2*h,"Sx",j;
- end
- H = MPO(os,sites)
-
-
- #
- # Make sure to do lots of sweeps
- # when finding excited states
- #
- nsweeps = 30
- maxdim = [10,10,10,20,20,40,80,100,200,200]
- cutoff = [1E-8]
- noise = [1E-6]
-
- #
- # Compute the ground state psi0
- #
- psi0_init = random_mps(sites;linkdims=2)
- energy0,psi0 = dmrg(H,psi0_init;nsweeps,maxdim,cutoff,noise)
-
- println()
-
- #
- # Compute the first excited state psi1
- #
- psi1_init = random_mps(sites;linkdims=2)
- energy1,psi1 = dmrg(H,[psi0],psi1_init;nsweeps,maxdim,cutoff,noise,weight)
-
- # Check psi1 is orthogonal to psi0
- @show inner(psi1,psi0)
-
-
- #
- # The expected gap of the transverse field Ising
- # model is given by Eg = 2*|h-1|
- #
- # (The DMRG gap will have finite-size corrections)
- #
- println("DMRG energy gap = ",energy1-energy0);
- println("Theoretical gap = ",2*abs(h-1));
-
- println()
-
- #
- # Compute the second excited state psi2
- #
- psi2_init = random_mps(sites;linkdims=2)
- energy2,psi2 = dmrg(H,[psi0,psi1],psi2_init;nsweeps,maxdim,cutoff,noise,weight)
-
- # Check psi2 is orthogonal to psi0 and psi1
- @show inner(psi2,psi0)
- @show inner(psi2,psi1)
-
- return
-end
-```
-
-## Printing the Entanglement Entropy at Each Step
-
-To obtain the entanglement entropy of an MPS at each step during a DMRG calculation,
-you can use the [Observer](@ref observer) system to make a custom observer object that prints out
-this information.
-
-First we define our custom observer type, `EntanglementObserver`, and overload the `measure!` function
-for it:
-
-```julia
-using ITensors, ITensorMPS
-
-mutable struct EntanglementObserver <: AbstractObserver
-end
-
-function ITensorMPS.measure!(o::EntanglementObserver; bond, psi, half_sweep, kwargs...)
- wf_center, other = half_sweep==1 ? (psi[bond+1],psi[bond]) : (psi[bond],psi[bond+1])
- U,S,V = svd(wf_center, uniqueinds(wf_center,other))
- SvN = 0.0
- for n=1:dim(S, 1)
- p = S[n,n]^2
- SvN -= p * log(p)
- end
- println(" Entanglement across bond $bond = $SvN")
-end
-```
-
-The `measure!` function grabs certain helpful keywords passed to it by DMRG, such as what bond DMRG
-has just finished optimizing.
-
-Here is a complete sample code including constructing the observer and passing it to DMRG:
-
-```julia
-using ITensors, ITensorMPS
-
-mutable struct EntanglementObserver <: AbstractObserver
-end
-
-function ITensorMPS.measure!(o::EntanglementObserver; bond, psi, half_sweep, kwargs...)
- wf_center, other = half_sweep==1 ? (psi[bond+1],psi[bond]) : (psi[bond],psi[bond+1])
- U,S,V = svd(wf_center, uniqueinds(wf_center,other))
- SvN = 0.0
- for n=1:dim(S, 1)
- p = S[n,n]^2
- SvN -= p * log(p)
- end
- println(" Entanglement across bond $bond = $SvN")
-end
-
-let
- N = 100
-
- s = siteinds("S=1/2",N)
-
- a = OpSum()
- for n=1:N-1
- a += "Sz",n,"Sz",n+1
- a += 0.5,"S+",n,"S-",n+1
- a += 0.5,"S-",n,"S+",n+1
- end
- H = MPO(a,s)
- psi0 = random_mps(s;linkdims=4)
-
- nsweeps = 5
- maxdim = [10,20,80,160]
- cutoff = 1E-8
-
- observer = EntanglementObserver()
-
- energy,psi = dmrg(H,psi0;nsweeps,maxdim,cutoff,observer,outputlevel=2)
-
- return
-end
-```
-
-Example output:
-```
-...
-Sweep 2, half 2, bond (35,36) energy=-44.08644657103751
- Truncated using cutoff=1.0E-08 maxdim=20 mindim=1
- Trunc. err=2.54E-07, bond dimension 20
- Entanglement across bond 35 = 0.7775882479059774
-Sweep 2, half 2, bond (34,35) energy=-44.086696891668424
- Truncated using cutoff=1.0E-08 maxdim=20 mindim=1
- Trunc. err=2.12E-07, bond dimension 20
- Entanglement across bond 34 = 0.7103532704635472
-Sweep 2, half 2, bond (33,34) energy=-44.08696190368391
- Truncated using cutoff=1.0E-08 maxdim=20 mindim=1
- Trunc. err=1.29E-07, bond dimension 20
- Entanglement across bond 33 = 0.7798362911744212
-...
-```
-
-If you only want to see the maximum entanglement during each sweep, you can add a field to the EntanglementObserver
-object that saves the maximum value encountered so far and keep overwriting this field, printing out the most recently observed maximum at the end of each sweep.
-
-
-## Monitoring the Memory Usage of DMRG
-
-To monitor how much memory (RAM) a DMRG calculation is using while it is running,
-you can use the [Observer](@ref observer) system to make a custom observer object that prints out
-this information. Also the `Base.summarysize` function, which returns the size
-in bytes of any Julia object is very helpful here.
-
-First we define our custom observer type, `SizeObserver`, and overload the `measure!` function
-for it:
-
-```julia
-using ITensors, ITensorMPS
-
-mutable struct SizeObserver <: AbstractObserver
-end
-
-function ITensorMPS.measure!(o::SizeObserver; bond, half_sweep, psi, projected_operator, kwargs...)
- if bond==1 && half_sweep==2
- psi_size = Base.format_bytes(Base.summarysize(psi))
- PH_size = Base.format_bytes(Base.summarysize(projected_operator))
- println("|psi| = $psi_size, |PH| = $PH_size")
- end
-end
-```
-
-The `measure!` function grabs certain helpful keywords passed to it by DMRG, checking
-`if bond==1 && half_sweep==2` so that it only runs when at the end of a full sweep.
-
-When it runs, it calls `Base.summarysize` on the wavefunction `psi` object and the `projected_operator` object. The `projected_operator`, which is the matrix (Hamiltonian) wrapped into the current MPS basis, is usually the largest-sized object in a DMRG calculation. The code also uses `Base.format_bytes` to turn an integer representing bytes into a human-readable string.
-
-Here is a complete sample code including constructing the observer and passing it to DMRG:
-
-```julia
-using ITensors, ITensorMPS
-
-mutable struct SizeObserver <: AbstractObserver
-end
-
-function ITensorMPS.measure!(o::SizeObserver; bond, sweep, half_sweep, psi, projected_operator, kwargs...)
- if bond==1 && half_sweep==2
- psi_size = Base.format_bytes(Base.summarysize(psi))
- PH_size = Base.format_bytes(Base.summarysize(projected_operator))
- println("After sweep $sweep, |psi| = $psi_size, |PH| = $PH_size")
- end
-end
-
-let
- N = 100
-
- s = siteinds("S=1/2",N)
-
- a = OpSum()
- for n=1:N-1
- a += "Sz",n,"Sz",n+1
- a += 0.5,"S+",n,"S-",n+1
- a += 0.5,"S-",n,"S+",n+1
- end
- H = MPO(a,s)
- psi0 = random_mps(s;linkdims=4)
-
- nsweeps = 5
- maxdim = [10,20,80,160]
- cutoff = 1E-8
-
- obs = SizeObserver()
-
- energy,psi = dmrg(H,psi0;nsweeps,maxdim,cutoff,observer=obs)
-
- return
-end
-```
-
-Example output:
-```
-After sweep 1, |psi| = 211.312 KiB, |PH| = 593.984 KiB
-After sweep 1 energy=-43.95323393592883 maxlinkdim=10 maxerr=8.26E-06 time=0.098
-After sweep 2, |psi| = 641.000 KiB, |PH| = 1.632 MiB
-After sweep 2 energy=-44.10791340895817 maxlinkdim=20 maxerr=7.39E-07 time=0.132
-After sweep 3, |psi| = 1.980 MiB, |PH| = 5.066 MiB
-After sweep 3 energy=-44.12593605906466 maxlinkdim=44 maxerr=9.96E-09 time=0.256
-After sweep 4, |psi| = 2.863 MiB, |PH| = 7.246 MiB
-After sweep 4 energy=-44.127710946536645 maxlinkdim=56 maxerr=9.99E-09 time=0.445
-After sweep 5, |psi| = 3.108 MiB, |PH| = 7.845 MiB
-After sweep 5 energy=-44.127736798226536 maxlinkdim=57 maxerr=9.98E-09 time=0.564
-```
diff --git a/docs/src/examples/ITensor.md b/docs/src/examples/ITensor.md
deleted file mode 100644
index aec5384f6f..0000000000
--- a/docs/src/examples/ITensor.md
+++ /dev/null
@@ -1,558 +0,0 @@
-# [ITensor Code Examples](@id itensor_examples)
-
-
-## Print Indices of an ITensor
-
-Sometimes the printout of an ITensor can be rather large, whereas you
-might only want to see its indices. For these cases, just wrap the
-ITensor in the function `inds` like this:
-
-```julia
-@show inds(T)
-```
-
-or this
-
-```julia
-println("T inds = ",inds(T))
-```
-
-## Getting and Setting Elements of an ITensor
-
-Say we have an ITensor constructed as:
-
-```julia
-i = Index(3,"index_i")
-j = Index(2,"index_j")
-k = Index(4,"index_k")
-
-T = ITensor(i,j,k)
-```
-
-An ITensor constructed this way starts with all of its elements
-equal to zero. (Technically it allocates no storage at all but this is
-an implementation detail.)
-
-**Setting Elements**
-
-To set an element of this ITensor, such as the element where `(i,j,k) = (2,1,3)`,
-you can do the following:
-
-```julia
-T[i=>2,j=>1,k=>3] = -3.2
-```
-
-In the Julia language, the notation `a=>b` is a built-in notation for making a `Pair(a,b)`
-object.
-
-Because the Index objects are passed to `T` along with their values, passing them in a different order has exactly the same effect:
-
-```julia
-# Both of these lines of code do the same thing:
-T[j=>1,i=>2,k=>3] = -3.2
-T[j=>1,k=>3,i=>2] = -3.2
-```
-
-**Getting Elements**
-
-You can retrieve individual elements of an ITensor by accessing them through the same notation used to set elements:
-
-```julia
-el = T[j=>1,i=>2,k=>3]
-println("The (i,j,k) = (2,1,3) element of T is ",el)
-```
-
-## Making ITensors from Arrays
-
-To initialize all of the elements of an ITensor at once, you
-can pass a Julia array into the ITensor constructor.
-
-For example, if we want to construct an ITensor `A` with indices
-`i,j` we can initialize it from a matrix as follows:
-
-```julia
-M = [1.0 2.0;
- 3.0 4.0]
-
-i = Index(2,"i")
-j = Index(2,"j")
-
-A = ITensor(M,i,j)
-```
-
-More generally we can use an nth-order (n-dimensional) Julia array to initialize an ITensor:
-
-```julia
-T = randn(4,7,2)
-
-k = Index(4,"index_k")
-l = Index(7,"index_l")
-m = Index(2,"index_m")
-
-B = ITensor(T,k,l,m)
-```
-
-## Making Arrays from ITensors
-
-Not only can we make an ITensor from a Julia array, but we can also convert
-an ITensor back into a Julia array.
-
-Say we have made an ITensor with two indices:
-
-```@example from_array
-using ITensors # hide
-k = Index(4,"index_k")
-m = Index(2,"index_m")
-
-T = random_itensor(k,m)
-@show T
-display(T) # hide
-```
-
-Here we used the `random_itensor` constructor to fill T with random elements
-but we could make an ITensor some other way too.
-
-Now to convert `T` into a regular Julia array `A`, use the [`Array`](@ref) constructor
-and pass the indices of `T` in the order that you want:
-
-```@example from_array
-A = Array(T,k,m)
-@show A
-```
-
-The reason you have to pass the indices is that the ordering of ITensor indices
-is an implementation detail and not part of the user interface. So when leaving the
-ITensor system and converting to a regular array, you must say what ordering of the
-indices you want. Making the array as `A = Array(T,m,k)` would give the transpose
-of the array in the code above.
-
-Note that for efficiency reasons, the array returned by the `array` function will
-sometimes be a *view* of the ITensor, such that changing an element of `A` would
-also change the corresponding element of `T`. This is not always the case though:
-for example if the indices are passed in a different order from how the internal
-ITensor storage is arranged, or if `T` is a block-sparse ITensor, since the
-(not stored) zero blocks will need to be filled in.
-
-
-## Arithmetic With ITensors
-
-ITensors can be added and subtracted and multiplied by scalars just like plain tensors can. But ITensors have the additional feature that you can add and subtract them even if their indices are in a different order from each other, as long as they have the same collection of indices.
-
-For example, say we have ITensors `A`, `B`, and `C`:
-```julia
-i = Index(3,"i")
-j = Index(2,"j")
-k = Index(4,"k")
-
-A = random_itensor(i,j,k)
-B = random_itensor(i,j,k)
-C = random_itensor(k,i,j)
-```
-Above we have initialized these ITensors to have random elements, just for the sake of this example.
-
-We can then add or subtract these ITensors
-
-```julia
-R1 = A + B
-R2 = A - B
-R3 = A + B - C
-```
-
-or do more complicated operations involving real and complex scalars too:
-
-```julia
-R4 = 2.0*A - B + C/(1+1im)
-```
-
-## Elementwise Operations on ITensors
-
-[*Note: currently elementwise operations are only defined for dense ITensors, not for block-sparse QN ITensors.*]
-
-ITensors support Julia broadcasting operations, making it quite easy to carry out element-wise operations on them in a very similar way as for regular Julia arrays. As a concrete example, consider the following ITensor initialized with random elements
-
-```julia
-i = Index(2,"i")
-j = Index(3,"j")
-
-A = random_itensor(i,j)
-```
-
-Here are some examples of basic element-wise operations we can do using Julia's dotted operator broadcasting syntax.
-
-```julia
-# Multiply every element of `A` by 2.0:
-A .*= 2.0
-```
-
-```julia
-# Add 1.5 to every element of A
-A .+= 1.5
-```
-
-The dotted notation works for functions too:
-
-```julia
-# Replace every element in A by its absolute value:
-A .= abs.(A)
-```
-
-```julia
-# Replace every element in A by the number 1.0
-A .= one.(A)
-```
-
-If have another ITensor `B = ITensor(j,i)`, which has the same set of indices
-though possibly in a different order, then we can also do element-wise operations
-involving both ITensors:
-
-```julia
-# Add elements of A and B element-wise
-A .= A .+ B
-# Add elements of A and B element-wise with coefficients included
-A .= (2.0 .* A) .+ (-3.0 .* B)
-```
-
-Last but not least, it is possible to make custom functions yourself and broadcast them across elements of ITensors:
-
-```julia
-myf(x) = 1.0/(1.0+exp(-x))
-T .= myf.(T)
-```
-
-## Making an ITensor with a Single Non-Zero Element
-
-It is often useful to make ITensors with all elements zero
-except for a specific element that is equal to 1.0.
-Use cases can include making product-state quantum wavefunctions
-or contracting single-element ITensors with other ITensors to
-set their indices to a fixed value.
-
-To make such an ITensor, use the [`onehot`](@ref) function. Borrowing terminology from engineering,
-a "one hot" vector or tensor has a single element equal to 1.0 and
-the rest zero. (In previous versions of ITensor this function was called `setelt`.)
-
-The ITensor function [`onehot`](@ref) takes one or more
-Index-value Pairs such as `i=>2` and `j=>1` and returns an ITensor
-with a 1.0 in the location specified by the Index values:
-
-```@example onehot_1
-using ITensors # hide
-i = Index(2)
-O1 = onehot(i=>1)
-println(O1)
-```
-
-```@example onehot_2
-using ITensors # hide
-i = Index(2) # hide
-O2 = onehot(i=>2)
-println(O2)
-```
-
-```@example onehot_3
-using ITensors # hide
-i = Index(2) # hide
-j = Index(3)
-T = onehot(i=>2,j=>3)
-println(T)
-```
-
-## Tracing an ITensor
-
-An important operation involving a single tensor is tracing out certain
-pairs of indices. Say we have an ITensor `A` with indices `i,j,l`:
-
-```julia
-i = Index(4,"i")
-j = Index(3,"j")
-l = Index(4,"l")
-
-A = random_itensor(i,j,l)
-```
-
-and we want to trace `A` by summing over the indices `i` and `l` locked together,
-in other words: ``\sum_{i} A^{iji}``.
-
-To do this in ITensor, we can use a `delta` tensor, which you can think of as
-an identity operator or more generally a Kronecker delta or "hyper-edge":
-
-![](itensor_trace_figures/delta_itensor.png)
-
-Viewed as an array, a delta tensor has all diagonal elements equal to 1.0 and
-zero otherwise.
-
-Now we can compute the trace by contracting `A` with the delta tensor:
-
-```julia
-trA = A * delta(i,l)
-```
-
-![](itensor_trace_figures/trace_A.png)
-
-## Factoring ITensors (SVD, QR, etc.)
-
-The ITensor approach to tensor factorizations emphasizes the structure
-of the factorization, and does not require knowing the index ordering.
-
-ITensor offers various tensor factorizations, such as the
-singular value decomposition (SVD) and the QR factorization.
-These are extended to the case of tensors by treating some of the indices
-as the "row" indices and the rest of the indices as the "column" indices,
-reshaping the tensor into a matrix to carry out the factorization, then
-restoring the tensor structure at the end. All of these steps are done
-for you by the ITensor system as we will see below.
-
-#### Singular Value Decomposition
-
-The singular value decomposition (SVD) is a matrix factorization
-that is also extremely useful for general tensors.
-
-As a brief review, the SVD is a factorization of a matrix M into the product
-```math
-M = U S V^\dagger
-```
-with U and V having the property ``U^\dagger U = 1`` and ``V^\dagger V = 1``.
-The matrix S is diagonal and has real, non-negative entries known as the singular
-values, which are typically ordered from largest to smallest.
-The SVD is well-defined for any matrix, including rectangular matrices. It also
-leads to a controlled approximation, where the error due to discarding columns of U and V
-is small if the corresponding singular values discarded are small.
-
-To compute the SVD of an ITensor, you only need to specify which indices are (collectively)
-the "row" indices (thinking of the ITensor as a matrix), with the rest assumed to be the "column"
-indices.
-
-Say we have an ITensor with indices i,j, and k
-
-```julia
-T = ITensor(i,j,k)
-```
-
-and we want to treat i and k as the "row" indices for the purpose of the SVD.
-
-To perform this SVD, we can call the function `svd` as follows:
-
-```julia
-U,S,V = svd(T,(i,k))
-```
-
-Diagrammatically the SVD operation above looks like:
-
-![](itensor_factorization_figures/SVD_Ex1.png)
-
-The guarantee of the `svd` function is that the ITensor
-product `U*S*V` gives us back an ITensor identical to T:
-
-```julia
-@show norm(U*S*V - T) # typical output: norm(U*S*V-T) = 1E-14
-```
-
-*Full working example:*
-
-```julia
-i = Index(3,"i")
-j = Index(4,"j")
-k = Index(5,"k")
-
-T = random_itensor(i,j,k)
-
-U,S,V = svd(T,(i,k))
-
-@show norm(U*S*V-T)
-```
-
-**Truncated SVD**
-
-An important use of the SVD is approximating a higher-rank tensor
-by a product of lower-rank tensors whose indices range over only
-a modest set of values.
-
-To obtain an approximate SVD in ITensor, pass one or more of
-the following accuracy parameters as named arguments:
-
-* `cutoff` --- real number ``\epsilon``. Discard the smallest singular values
- ``\lambda\_n`` such that the truncation error is less than ``\epsilon``:
- $$
- \frac{\sum\_{n\in\text{discarded}} \lambda^2\_n}{\sum\_{n} \lambda^2\_n} < \epsilon \:.
- $$
- Using a cutoff allows the SVD algorithm to truncate as many states as possible while still
- ensuring a certain accuracy.
-
-* `maxdim` --- integer M. If the number of singular values exceeds M, only the largest M will be retained.
-
-* `mindim` --- integer m. At least m singular values will be retained, even if some fall below the cutoff
-
-Let us revisit the example above, but also provide some of these accuracy parameters
-
-```julia
-i = Index(10,"i")
-j = Index(40,"j")
-k = Index(20,"k")
-T = random_itensor(i,j,k)
-
-U,S,V = svd(T,(i,k),cutoff=1E-2)
-```
-
-Note that we have also made the indices larger so that the truncation performed will be
-non-trivial.
-In the code above, we specified that a cutoff of ``\epsilon=10^{-2}`` be used. We can check that the resulting factorization is now approximate by computing the squared relative error:
-
-```julia
-truncerr = (norm(U*S*V - T)/norm(T))^2
-@show truncerr
-# typical output: truncerr = 8.24E-03
-```
-
-Note how the computed error is below the cutoff ``\epsilon`` we requested.
-
-*Full working example including truncation:*
-
-```julia
-i = Index(10,"i");
-j = Index(40,"j");
-k = Index(20,"k");
-
-T = random_itensor(i,j,k)
-
-U,S,V = svd(T,(i,k),cutoff=1E-2)
-
-@show norm(U*S*V-T)
-@show (norm(U*S*V - T)/norm(T))^2
-```
-
-#### QR Factorization
-
-Computing the QR factorization of an ITensor works in a similar way as for the SVD.
-In addition to passing the ITensor you want to factorize, you must also pass
-the indices you want to end up on the tensor `Q`, in other words to be treated
-as the "row" indices for the purpose of defining the QR factorization.
-
-Say we want to compute the QR factorization of an ITensor `T` with indices `i,j,k`,
-putting the indices `i` and `k` onto `Q` and the remaining indices onto `R`. We
-can do this as follows:
-
-![](itensor_factorization_figures/QR_Ex1.png)
-
-```julia
-T = random_itensor(i,j,k)
-Q,R = qr(T,(i,k);positive=true)
-```
-
-Note the use of the optional `positive=true` keyword argument, which ensures that
-the diagonal elements of `R` are non-negative. With this option, the QR factorization
-is *unique*, which can be useful in certain cases.
-
-## Combining Multiple Indices into One Index
-
-It can be very useful to combine or merge multiple indices of an ITensor into a
-single Index. Say we have an ITensor with indices `i,j,k` and we want to combine
-Index `i` and Index `k` into a new Index. This new Index (call it `c`) will have
-a dimension whose size is the dimension of `i` times the dimension of `k`.
-
-To carry out this procedure we can make a special kind of ITensor: a combiner.
-To make a combiner, call the function `combiner`, passing the indices you
-want to combine:
-```@example combiner
-using ITensors # hide
-i = Index(4,"i") # hide
-j = Index(3,"j") # hide
-k = Index(2,"k") # hide
-C = combiner(i,k; tags="c")
-nothing # hide
-```
-
-Then if we have an ITensor
-```@example combiner
-T = random_itensor(i,j,k)
-@show inds(T)
-```
-we can combine indices `i` and `k` by contracting with the combiner:
-```@example combiner
-CT = C * T
-nothing # hide
-```
-
-Printing out the indices of the new ITensor `CT` we can see that it
-has only two indices:
-```@example combiner
-@show inds(CT)
-```
-The first is the newly made combined Index, which was made for us by
-the `combiner` function and the second is the `j` Index of `T`
-which was not part of the combining process. To access the combined
-Index you can call the `combinedind` function on the combiner:
-```@example combiner
-ci = combinedind(C)
-```
-
-We can visualize all of the steps above as follows:
-![](combiner_itensor.png)
-
-Combining is not limited to two indices and you can
-combine any number of indices, in any order, using a combiner.
-
-To undo the combining process and uncombine the Index `c` back into `i,k`,
-just contract with the conjugate of the combiner ITensor `dag(C)`.
-```@example combiner
-UT = dag(C) * CT
-@show inds(UT)
-```
-
-
-## Write and Read an ITensor to Disk with HDF5
-
-
-
-!!! info
- Make sure to install the HDF5 package to use this feature. (Run `julia> ] add HDF5` in the Julia REPL console.)
-
-Saving ITensors to disk can be very useful. For example, you
-might encounter a bug in your own code, and by reading the
-ITensors involved from disk you can shortcut the process of
-running a lengthy algorithm over many times to reproduce the bug.
-Or you can save the output of an expensive calculation, such as
-a DMRG calculation, and use it as a starting point for multiple
-follow-up calculations such as computing time-dependent properties.
-
-ITensors can be written to files using the HDF5 format. HDF5 offers
-many benefits such as being portable across different machine types,
-and offers a standard interface across various libraries and languages.
-
-**Writing an ITensor to an HDF5 File**
-
-Let's say you have an ITensor `T` which you have made or obtained
-from a calculation. To write it to an HDF5 file named "myfile.h5"
-you can use the following pattern:
-
-```julia
-using HDF5
-f = h5open("myfile.h5","w")
-write(f,"T",T)
-close(f)
-```
-
-Above, the string "T" can actually be any string you want such as "ITensor T"
-or "Result Tensor" and doesn't have to have the same name as the reference `T`.
-Closing the file `f` is optional and you can also write other objects to the same
-file before closing it.
-
-**Reading an ITensor from an HDF5 File**
-
-Say you have an HDF5 file "myfile.h5" which contains an ITensor stored as a dataset with the
-name "T". (Which would be the situation if you wrote it as in the example above.)
-To read this ITensor back from the HDF5 file, use the following pattern:
-
-```julia
-using HDF5
-f = h5open("myfile.h5","r")
-T = read(f,"T",ITensor)
-close(f)
-```
-
-Note the `ITensor` argument to the read function, which tells Julia which read function
-to call and how to interpret the data stored in the HDF5 dataset named "T". In the
-future we might lift the requirement of providing the type and have it be detected
-automatically from the data stored in the file.
-
-
-
diff --git a/docs/src/examples/MPSandMPO.md b/docs/src/examples/MPSandMPO.md
deleted file mode 100644
index c8ee559261..0000000000
--- a/docs/src/examples/MPSandMPO.md
+++ /dev/null
@@ -1,454 +0,0 @@
-# MPS and MPO Examples
-
-The following examples demonstrate operations available in ITensor
-to work with [matrix product state (MPS)](http://tensornetwork.org/mps/)
-(or tensor train) and matrix product operator (MPO) tensor networks.
-
-## Creating an MPS from a Tensor
-
-![](mps_from_tensor.png)
-
-A matrix product state (MPS) made of N tensors, each with
-one site or physical index, is a way of representing a single
-tensor with N indices. One way of obtaining the MPS form of an
-N-index tensor `T` is by repeatedly factorizing `T` into N
-separate tensors using a factorization such as the [Singular Value Decomposition](@ref) (SVD).
-This algorithm for obtaining an MPS is known in the mathematics
-literature as the "tensor train SVD" or "TT-SVD" algorithm.
-
-To turn an N-index (order-N) tensor T into an MPS, you can just
-construct an MPS by passing T as the first argument, along with
-keyword arguments that control the approximations used in factorizing
-T. Let's look at a few specific cases.
-
-#### ITensor to MPS Example
-
-If you have a tensor `T` which is an ITensor and has indices `i,j,k,l,m`,
-you can create an MPS approximation of `T` where the MPS has site indices
-`i,j,k,l,m` as follows:
-
-```julia
-cutoff = 1E-8
-maxdim = 10
-T = random_itensor(i,j,k,l,m)
-M = MPS(T,(i,j,k,l,m);cutoff=cutoff,maxdim=maxdim)
-```
-
-Here we used a random ITensor for illustrative purposes, but it could be any ITensor and
-typically tensors with additional structure are more well approximated by MPS.
-
-#### Julia Tensor to MPS Example
-
-Another situation could be where you have a Julia array or Julia tensor of
-dimension ``d^N`` and want to approximate it as an MPS with ``N`` site indices,
-each of dimension ``d``. For example, we could have the following random Julia
-array of dimension ``2\times 2\times 2 \times 2 \times 2``:
-
-```julia
-d = 2
-N = 5
-A = randn(d,d,d,d,d)
-```
-
-Alternatively, the array could be just a one dimensional array of length ``d^N``:
-
-```julia
-A = randn(d^N)
-```
-
-To convert this array to an MPS, we will first need a collection of Index objects
-to use as the site indices of the MPS. We can conveniently construct an array of
-four indices of dimension 2 as follows:
-
-```julia
-sites = siteinds(d,N)
-```
-
-Finally, we can pass our array `A` and our `sites` to the MPS constructor along with
-parameters controlling the truncation level of the factorizations used:
-
-```julia
-cutoff = 1E-8
-maxdim = 10
-M = MPS(A,sites;cutoff=cutoff,maxdim=maxdim)
-```
-
-## Obtaining Elements of a Tensor Represented by an MPS
-
-A matrix product state (MPS) or tensor train (TT) is a format for representing a large tensor having N indices in terms of N smaller tensors. Given an MPS represeting a tensor T
-we can obtain a particular element ``T^{s_1 s_2 s_3 \cdots s_N}``
-of that tensor using code similar to the following code below.
-
-In the example code below we will obtain the element ``T^{1,2,1,1,2,1,2,2,2,1}`` of the tensor T
-which is (implicitly) defined by the MPS psi:
-
-```@example mps_element
-using ITensors, ITensorMPS
-let # hide
-N = 10
-s = siteinds(2,N)
-chi = 4
-psi = random_mps(s;linkdims=chi)
-
-# Make an array of integers of the element we
-# want to obtain
-el = [1,2,1,1,2,1,2,2,2,1]
-
-V = ITensor(1.)
-for j=1:N
- V *= (psi[j]*state(s[j],el[j]))
-end
-v = scalar(V)
-
-# v is the element we wanted to obtain:
-@show v
-end # hide
-```
-
-The call to `state(s[j],el[j])` in the code above makes a single-index ITensor
-with the Index `s[j]` and the entry at location `el[j]` set to 1.0, with all other
-entries set to 0.0. Contracting this tensor with the MPS tensor at site `j`
-can be viewed as "clamping" or "fixing" the index to a set value. The resulting
-tensors are contracted sequentially, overwriting the ITensor `V`, and the final
-scalar value of `V` is the tensor element we seek.
-
-See below for a visual depiction of what the above code is doing:
-
-![](mps_element.png)
-
-## Expected Value of Local Operators
-
-When using an MPS to represent a quantum wavefunction ``|\psi\rangle``
-a common operation is computing the expected value ``\langle\psi|\hat{A}_j|\psi\rangle``
-of a local operator ``\hat{A}_j`` acting on site ``j``. This can be accomplished
-efficiently and conveniently using the [`expect`](@ref) function as:
-
-```julia
-Avals = expect(psi,"A")
-```
-
-where `"A"` must be an operator associated with the physical site type, or site tags, of
-the sites of the MPS `psi`. For example, the operator name could be
-`"Sz"` for spin sites or `"Ntot"` for electron sites.
-(For more information about defining such operators yourself,
-see the section on [Extending op Function Definitions](@ref custom_op).)
-
-As a concrete example, consider computing the expectation value of ``S^z_j`` on
-every site of an MPS representing a system of N spins of size ``S=1/2``. In the
-following example we will use a random MPS of bond dimension ``\chi=4`` but the
-MPS could be obtained other ways such as through a DMRG calculation.
-
-```@example expect
-using ITensors, ITensorMPS
-N = 10
-chi = 4
-sites = siteinds("S=1/2",N)
-psi = random_mps(sites;linkdims=chi)
-magz = expect(psi,"Sz")
-for (j,mz) in enumerate(magz)
- println("$j $mz")
-end
-```
-
-![](mps_expect.png)
-
-## Expected Values of MPO Operators
-
-When using an MPS to represent a quantum wavefunction ``|\psi\rangle``
-another common operation is computing the expected value ``\langle\psi|W|\psi\rangle``
-of an operator ``W`` which is represented as a matrix product operator (MPO) tensor network.
-A key example could be the Hamiltonian defining a quantum system.
-
-Given an MPO `W` and an MPS `psi`, you can compute ``\langle\psi|W|\psi\rangle``
-by using the function `inner` as follows:
-```julia
-ex_W = inner(psi',W,psi)
-```
-which will return a scalar that may be either real or complex, depending on the properties of
-`psi` and `W`.
-
-## Computing Correlation Functions
-
-In addition to expected values of local operators
-discussed above, another type of observable that is very important
-in physics studies are correlation functions of the form
-
-```math
-C_{ij} = \langle\psi| A_i B_j |\psi\rangle
-```
-
-These can be computed efficiently for an MPS `psi` in ITensor
-using the [`correlation_matrix`](@ref) function:
-
-```julia
-C = correlation_matrix(psi,"A","B")
-```
-
-where `"A"` and `"B"` must be an operator names associated with the physical site type,
-or site tags, of the sites of the MPS `psi`. For example, these strings could be
-`"Sz"`, `"S+"`, or `"S-"` for spin sites, or `"Cdagup"` and `"Cup"` for electron sites.
-(For more information about defining such operators yourself,
-see the section on [Extending op Function Definitions](@ref custom_op).)
-
-As a concrete example, say we have an MPS `psi` for a system of spins and
-want to compute the correlator ``\langle\psi|S^z_i S^z_j|\psi\rangle``.
-We can compute this as:
-
-```julia
-zzcorr = correlation_matrix(psi,"Sz","Sz")
-```
-
-![](mps_zz_correlation.png)
-
-See the [`correlation_matrix`](@ref) docs for more details about additional arguments you can pass
-to this function.
-
-## Applying a Single-site Operator to an MPS
-
-In many applications one needs to modify a matrix product
-state (MPS) by multiplying it with an operator that acts
-only on a single site. This is actually a very straightforward
-operation and this formula shows you how to do it in ITensor.
-
-Say we have an operator ``G^{s'_3}_{s_3}`` which acts non-trivially on site 3 of our MPS `psi`
-as in the following diagram:
-
-![](mps_onesite_figures/operator_app_mps.png)
-
-To carry out this operation, contract the operator G with the MPS tensor for site 3,
-removing the prime from the ``s'_3`` index afterward:
-
-![](mps_onesite_figures/operator_contract.png)
-
-```julia
-newA = G * psi[3]
-newA = noprime(newA)
-```
-
-Finally, put the new tensor back into MPS `psi` to update its third MPS tensor:
-
-```julia
-psi[3] = newA
-```
-
-Afterward, we can visualize the modified MPS as:
-
-![](mps_onesite_figures/updated_mps.png)
-
-As a technical note, if you are working in a context where gauge or orthogonality
-properties of the MPS are important, such as in time evolution using two-site gates,
-then you may want to call `psi = orthogonalize(psi, 3)`
-before modifying the tensor at site 3, which will ensure that the MPS remains in a
-well-defined orthogonal gauge centered on site 3. Modifying a tensor which is left- or right-orthogonal
-(i.e. not the "center" tensor of the gauge) will destroy the gauge condition and
-require extra operations to restore it. (Calling `orthogonalize` method will automatically
-fix this but will have to do extra work to do so.)
-
-
-## Applying a Two-site Operator to an MPS
-
-A very common operation with matrix product states (MPS) is
-multiplication by a two-site operator or "gate" which modifies
-the MPS. This procedure can be carried out in an efficient,
-controlled way which is adaptive in the MPS bond dimension.
-
-Say we have an operator ``G^{s'_3 s'_4}_{s_3 s_4}`` which
-is our gate and which acts on physical sites 3 and 4 of our MPS `psi`,
-as in the following diagram:
-
-![](twosite_figures/gate_app_mps.png)
-
-To apply this gate in a controlled manner, first 'gauge' the MPS `psi` such
-that either site 3 or 4 is the *orthogonality center*. Here we make site 3
-the center:
-
-```julia
-psi = orthogonalize(psi, 3)
-```
-
-![](twosite_figures/gate_gauge.png)
-
-The other MPS tensors are now either left-orthogonal or right-orthogonal and can be
-left out of further steps without producing incorrect results.
-
-Next, contract the gate tensor G with the MPS tensors for sites 3 and 4
-
-![](twosite_figures/gate_contract.png)
-
-```julia
-wf = (psi[3] * psi[4]) * G
-wf = noprime(wf)
-```
-
-Finally, use the singular value decomposition (SVD) to factorize the
-resulting tensor, multiplying the singular values into either U or V.
-Assign these two tensors back into the MPS to update it.
-
-![](twosite_figures/gate_svd.png)
-
-```julia
-inds3 = uniqueinds(psi[3],psi[4])
-U,S,V = svd(wf,inds3,cutoff=1E-8)
-psi[3] = U
-psi[4] = S*V
-```
-
-The call to `uniqueinds(psi[3])` analyzes the indices of `psi[3]` and `psi[4]`
-and finds any which are unique to just `psi[3]`, saving this collection of indices as `inds3`.
-Passing this collection of indices to the `svd` function tells it to treat any indices
-that are unique to `psi[3]` as the indices which should go onto the `U` tensor afterward.
-We also set a truncation error cutoff of 1E-8 in the call to `svd` to truncate
-the smallest singular values and control the size of the resulting MPS.
-Other cutoff values can be used, depending on the desired accuracy,
-as well as limits on the maximum bond dimension (`maxdim` keyword argument).
-
-**Complete code example**
-
-```julia
-using ITensors, ITensorMPS
-
-psi = orthogonalize(psi, 3)
-
-wf = (psi[3] * psi[4]) * G
-wf = noprime(wf)
-
-inds3 = uniqueinds(psi[3], psi[4])
-U, S, V = svd(wf, inds3; cutoff=1E-8)
-psi[3] = U
-psi[4] = S * V
-```
-
-## Computing the Entanglement Entropy of an MPS
-
-A key advantage of using the matrix product state (MPS) format to represent quantum wavefunctions is that it allows one to efficiently compute the entanglement entropy of any left-right bipartition of the system in one dimension, or for a two-dimensional system any "cut" along the MPS path.
-
-Say that we have obtained an MPS `psi` of length N and we wish to compute the entanglement entropy of a bipartition of the system into a region "A" which consists of sites 1,2,...,b and a region B consisting of sites b+1,b+2,...,N.
-
-Then the following code formula can be used to accomplish this task:
-
-```julia
-psi = orthogonalize(psi, b)
-U,S,V = svd(psi[b], (linkinds(psi, b-1)..., siteinds(psi, b)...))
-SvN = 0.0
-for n=1:dim(S, 1)
- p = S[n,n]^2
- SvN -= p * log(p)
-end
-```
-
-As a brief explanation of the code above, the call to `psi = orthogonalize(psi, b)`
-shifts the orthogonality center to site `b` of the MPS.
-
-The call to the `svd` routine says to treat the link (virtual or bond) Index connecting the b'th MPS tensor `psi[b]` and the b'th physical Index as "row" indices for the purposes of the SVD (these indices will end up on `U`, along with the Index connecting `U` to `S`).
-
-The code in the `for` loop iterates over the diagonal elements of the `S` tensor (which are the singular values from the SVD), computes their squares to obtain the probabilities of observing the various states in the Schmidt basis (i.e. eigenvectors of the left-right bipartition reduced density matrices), and puts them into the von Neumann entanglement entropy formula ``S_\text{vN} = - \sum_{n} p_{n} \log{p_{n}}``.
-
-## Sampling from an MPS
-
-A matrix product state (MPS) can be viewed as defining a probability distribution
-through the Born rule, as is the case when the MPS represents a quantum wavefunction.
-To sample from the distribution defined by an MPS, you can use the function `sample`
-provided in ITensor. For an MPS `psi` call to `sample(psi)` returns a random
-sample from the distribution defined by `psi`. (Note that each sample is drawn anew
-and not from a Markov chain seeded by a previous sample; this is possible because
-the algorithm for sampling MPS is a `perfect' sampling algorithm with no autocorrelation.)
-
-In more detail, say we have a set of `N` site indices `s` and define a random MPS
-with these sites:
-```@example sample_mps; continued=true
-using ITensors, ITensorMPS
-
-N = 10 # number of sites
-d = 3 # dimension of each site
-chi = 16 # bond dimension of the MPS
-s = siteinds(d,N)
-psi = random_mps(s;linkdims=chi)
-```
-
-We can now draw some samples from this MPS as
-
-```@example sample_mps
-v1 = sample(psi)
-v2 = sample(psi)
-v3 = sample(psi)
-println(v1)
-println(v2)
-println(v3)
-```
-
-The integers in each of the samples represent settings of each of the MPS indices
-in the "computational basis".
-
-For reasons of efficiency, the `sample` function requires the MPS to be in orthogonal
-form, orthogonalized to the first site. If it is not already in this form, it
-can be brought into orthogonal form by calling `psi = orthogonalize(psi, 1)`.
-
-
-## Write and Read an MPS or MPO to Disk with HDF5
-
-!!! info
- Make sure to install the HDF5 package to use this feature. (Run `julia> ] add HDF5` in the Julia REPL console.)
-
-**Writing an MPS to an HDF5 File**
-
-Let's say you have an MPS `psi` which you have made or obtained
-from a calculation. To write it to an HDF5 file named "myfile.h5"
-you can use the following pattern:
-
-```julia
-using HDF5
-f = h5open("myfile.h5","w")
-write(f,"psi",psi)
-close(f)
-```
-
-Above, the string "psi" can actually be any string you want such as "MPS psi"
-or "Result MPS" and doesn't have to have the same name as the reference `psi`.
-Closing the file `f` is optional and you can also write other objects to the same
-file before closing it.
-
-**Reading an MPS from an HDF5 File**
-
-Say you have an HDF5 file "myfile.h5" which contains an MPS stored as a dataset with the
-name "psi". (Which would be the situation if you wrote it as in the example above.)
-To read this ITensor back from the HDF5 file, use the following pattern:
-
-```julia
-using HDF5
-f = h5open("myfile.h5","r")
-psi = read(f,"psi",MPS)
-close(f)
-```
-
-Many functions which involve MPS, such as the `dmrg` function or the `OpSum` system
-require that you use an array of site indices which match the MPS. So when reading in
-an MPS from disk, do not construct a new array of site indices. Instead, you can
-obtain them like this: `sites = siteinds(psi)`.
-
-So for example, to create an MPO from an OpSum which has the same site indices
-as your MPS `psi`, do the following:
-
-```julia
-using ITensors, ITensorMPS
-
-os = OpSum()
-# Then put operators into os...
-
-sites = siteinds(psi) # Get site indices from your MPS
-H = MPO(os,sites)
-
-# Compute
-energy_psi = inner(psi',H,psi)
-```
-
-Note the `MPS` argument to the read function, which tells Julia which read function
-to call and how to interpret the data stored in the HDF5 dataset named "psi". In the
-future we might lift the requirement of providing the type and have it be detected
-automatically from the data stored in the file.
-
-
-**Writing and Reading MPOs**
-
-To write or read MPOs to or from HDF5 files, just follow the examples above but use
-the type `MPO` when reading an MPO from the file instead of the type `MPS`.
-
diff --git a/docs/src/examples/Physics.md b/docs/src/examples/Physics.md
deleted file mode 100644
index 751e76e4f4..0000000000
--- a/docs/src/examples/Physics.md
+++ /dev/null
@@ -1,549 +0,0 @@
-# Physics (SiteType) System Examples
-
-## Obtaining a Predefined Operator
-
-Given an Index carrying a "physical" tag such as "Qubit", "S=1/2", "Boson", etc.
-there are a set of pre-defined operators for each tag. The entire set of operators
-can be found in the section [SiteTypes Included with ITensor](@ref).
-
-If you have an Index `s` carrying a "S=1/2" tag, for example, you can obtain the "Sz"
-operator like this:
-```julia
-using ITensors, ITensorMPS
-
-op("Sz",s)
-```
-
-Usually indices with physical tags come from an array of indices returned from the `siteinds` function
-```julia
-using ITensors, ITensorMPS
-
-N = 10
-sites = siteinds("S=1/2",N)
-```
-in which case one might want the "Sz" operator on site 4
-```julia
-using ITensors, ITensorMPS
-Sz4 = op("Sz",sites[4])
-```
-
-## Make a Custom Operator from a Matrix
-
-The `op` function can be passed any matrix, as long as it has the correct dimensions,
-and it will make this into an ITensor representing the operator with the corresponding
-matrix elements.
-
-For example, if we have a two-dimensional Index `s` we could make the "Sz" operator ourselves from
-the matrix
-```julia
-M = [1/2 0 ; 0 -1/2]
-```
-by calling
-```julia
-using ITensors, ITensorMPS
-Sz = op(M,s)
-```
-
-
-## [Making a Custom op Definition](@id custom_op)
-
-The function `op` is used to obtain operators defined for a
-given "site type". ITensor includes pre-defined site types such
-as "S=1/2", "S=1", "Electron" and others. Or you can define your own site type
-as discussed in detail in the code examples further below.
-
-**Extending op Function Definitions**
-
-Perhaps the most common part of the site type system one wishes to extend
-are the various `op` or `op!` function overloads which allow code like
-
-```julia
-using ITensors, ITensorMPS
-s = siteind("S=1/2")
-Sz = op("Sz",s)
-```
-
-to automatically create the ``S^z`` operator for an Index `s` based on the
-`"S=1/2"` tag it carries. A major reason to define such `op` overloads
-is to allow the OpSum system to recognize new operator names, as
-discussed more below.
-
-Let's see how to introduce a new operator name into the ITensor site type
-system for this existing site type of `"S=1/2"`. The operator we will
-introduce is the projector onto the up spin state ``P_\uparrow`` which
-we will denote with the string `"Pup"`.
-
-As a matrix acting on the space ``\{ |\!\uparrow\rangle, |\!\downarrow\rangle \}``,
-the ``P_\uparrow`` operator is given by
-
-```math
-\begin{aligned}
-
-P_\uparrow &=
-\begin{bmatrix}
- 1 & 0 \\
- 0 & 0 \\
-\end{bmatrix}
-
-\end{aligned}
-```
-
-To add this operator to the ITensor `op` system, we just need to introduce the following
-code
-
-```julia
-using ITensors, ITensorMPS
-ITensors.op(::OpName"Pup",::SiteType"S=1/2") =
- [1 0
- 0 0]
-```
-
-This code can be defined anywhere, such as in your own personal application code and does
-not have to be put into the ITensor library source code.
-
-Note that we have to name the function `ITensors.op` and not just `op` so that it overloads
-other functions of the name `op` inside the ITensors module.
-
-Having defined the above code, we can now do things like
-
-```julia
-using ITensors, ITensorMPS
-s = siteind("S=1/2")
-Pup = op("Pup",s)
-```
-
-to obtain the `"Pup"` operator for our `"S=1/2"` Index `s`. Or we can do a similar
-thing for an array of site indices:
-
-```julia
-using ITensors, ITensorMPS
-N = 40
-s = siteinds("S=1/2",N)
-Pup1 = op("Pup",s[1])
-Pup3 = op("Pup",s[3])
-```
-
-Note that for the `"Qudit"`/`"Boson"` site types, you have to define your overload
-of `op` with the dimension of the local Hilbert space, for example:
-```julia
-using ITensors, ITensorMPS
-function ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int)
- o = zeros(d, d)
- o[1, 1] = 1
- return o
-end
-```
-Alternatively you could use Julia's [array comprehension](https://docs.julialang.org/en/v1/manual/arrays/#man-comprehensions) syntax:
-```julia
-using ITensors, ITensorMPS
-ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) =
- [(i == j == 1) ? 1.0 : 0.0 for i in 1:d, j in 1:d]
-```
-
-**Using Custom Operators in OpSum**
-
-A key use of these `op` system extensions is allowing additional operator names to
-be recognized by the OpSum system for constructing matrix product operator (MPO)
-tensor networks. With the code above defining the `"Pup"` operator, we are now
-allowed to use this operator name in any OpSum code involving `"S=1/2"` site
-indices.
-
-For example, we could now make an OpSum involving our custom operator such as:
-
-```julia
-using ITensors, ITensorMPS
-N = 100
-sites = siteinds("S=1/2",N)
-os = OpSum()
-for n=1:N
- os += "Pup",n
-end
-P = MPO(os,sites)
-```
-
-This code makes an MPO `P` which is just the sum of a spin-up projection operator
-acting on every site.
-
-
-## Making a Custom state Definition
-
-The function `state` is used to define states (single-site wavefunctions)
-that sites can be in. For example, the "Qubit" site type includes
-definitions for the "0" and "1" states as well as the "+" (eigenstate of X operator)
-state. The "S=1/2" site type includes definitions for the "Up" and "Dn" (down) states.
-
-Say we want to define a new state for the "Electron" site type called "+", which has
-the meaning of one electron with its spin in the +X direction. First let's review
-the existing state definitions:
-```julia
-using ITensors, ITensorMPS
-ITensors.state(::StateName"Emp", ::SiteType"Electron") = [1.0, 0, 0, 0]
-ITensors.state(::StateName"Up", ::SiteType"Electron") = [0.0, 1, 0, 0]
-ITensors.state(::StateName"Dn", ::SiteType"Electron") = [0.0, 0, 1, 0]
-ITensors.state(::StateName"UpDn", ::SiteType"Electron") = [0.0, 0, 0, 1]
-```
-As we can see, the four settings of an "Electron" index correspond to the states
-``|0\rangle, |\uparrow\rangle, |\downarrow\rangle, |\uparrow\downarrow\rangle``.
-
-So we can define our new state "+" as follows:
-```julia
-ITensors.state(::StateName"+", ::SiteType"Electron") = [0, 1/sqrt(2), 1/sqrt(2), 0]
-```
-which makes the state
-```math
-|+\rangle = \frac{1}{\sqrt{2}} |\uparrow\rangle + \frac{1}{\sqrt{2}} |\downarrow\rangle
-```
-
-Having defined this overload of `state`, if we have an Index of type "Electron"
-we can obtain our new state for it by doing
-```julia
-using ITensors, ITensorMPS
-s = siteind("Electron")
-plus = state("+",s)
-```
-We can also use this new state definition in other ITensor features such as
-the MPS constructor taking an array of state names.
-
-
-## Make a Custom Local Hilbert Space / Physical Degree of Freedom
-
-ITensor provides support for a range of common local Hilbert space types,
-or physical degrees of freedom, such as S=1/2 and S=1 spins; spinless and spinful
-fermions; and more.
-
-However, there can be many cases where you need to make custom
-degrees of freedom. You might be working with an
-exotic system, such as ``Z_N`` parafermions for example, or need
-to customize other defaults provided by ITensor.
-
-In ITensor, such a customization is done by overloading functions
-on specially designated Index tags.
-Below we give an brief introduction by example of how to make
-such custom Index site types in ITensor.
-Other code formulas following this one explain how to build on this
-example to expand the capabilities of your custom site type such as
-adding support for quantum number (QN) conservation and defining
-custom mappings of strings to states.
-
-Throughout we will focus on the example of ``S=3/2`` spins. These
-are spins taking the ``S^z`` values of ``+3/2,+1/2,-1/2,-3/2``.
-So as tensor indices, they are indices of dimension 4.
-
-The key operators we will make for this example are ``S^z``, ``S^+``,
-and ``S^-``, which are defined as:
-
-```math
-\begin{aligned}
-S^z &=
-\begin{bmatrix}
-3/2 & 0 & 0 & 0 \\
- 0 & 1/2 & 0 & 0 \\
- 0 & 0 &-1/2 & 0 \\
- 0 & 0 & 0 &-3/2\\
-\end{bmatrix} \\
-
-S^+ & =
-\begin{bmatrix}
- 0 & \sqrt{3} & 0 & 0 \\
- 0 & 0 & 2 & 0 \\
- 0 & 0 & 0 & \sqrt{3} \\
- 0 & 0 & 0 & 0 \\
-\end{bmatrix} \\
-
-S^- & =
-\begin{bmatrix}
- 0 & 0 & 0 & 0 \\
- \sqrt{3} & 0 & 0 & 0 \\
- 0 & 2 & 0 & 0 \\
- 0 & 0 & \sqrt{3} & 0 \\
-\end{bmatrix} \\
-\end{aligned}
-```
-
-**Code Preview**
-
-First let's see the minimal code needed to define and use this new
-``S=3/2`` site type, then we will discuss what each part of
-the code is doing.
-
-```julia
-using ITensors, ITensorMPS
-
-ITensors.space(::SiteType"S=3/2") = 4
-
-ITensors.op(::OpName"Sz",::SiteType"S=3/2") =
- [+3/2 0 0 0
- 0 +1/2 0 0
- 0 0 -1/2 0
- 0 0 0 -3/2]
-
-ITensors.op(::OpName"S+",::SiteType"S=3/2") =
- [0 √3 0 0
- 0 0 2 0
- 0 0 0 √3
- 0 0 0 0]
-
-ITensors.op(::OpName"S-",::SiteType"S=3/2") =
- [0 0 0 0
- √3 0 0 0
- 0 2 0 0
- 0 0 √3 0]
-
-```
-
-Now let's look at each part of the code above.
-
-**The SiteType**
-
-The most important aspect of this code is a special type, known as a `SiteType`,
-which is a type made from a string. The string of interest here will be an Index
-tag. In the code above, the `SiteType` we are using is
-
-```julia
-SiteType"S=3/2"
-```
-
-What is the purpose of a `SiteType`? The answer is that we would like to be
-able to select different functions to call on an ITensor Index based on what tags
-it has, but that is not directly possible in Julia or indeed most languages.
-However, if we can map a tag
-to a type in the Julia type system, we can create function overloads for that type.
-ITensor does this for certain functions for you, and we will discuss a few of these
-functions below. So if the code encounters an Index such as `Index(4,"S=3/2")` it can
-call these functions which are specialized for indices carrying the `"S=3/2"` tag.
-
-**The space Function**
-
-One of the overloadable `SiteType` functions is `space`, whose job is to
-describe the vector space corresponding to that site type. For our
-`SiteType"S=3/2"` overload of `space`, which gets called for any Index
-carrying the `"S=3/2"` tag, the definition is
-
-```julia
-using ITensors, ITensorMPS
-ITensors.space(::SiteType"S=3/2") = 4
-```
-
-Note that the function name is prepended with `ITensors.` before `space`.
-This prefix makes sure the function is overloading other versions of the `space`
-inside the `ITensors` module.
-
-The only information needed about the vector space of a `"S=3/2"` Index in
-this example is that it is of dimension four. So the `space` function returns
-the integer `4`. We will see in more advanced examples that the returned value
-can instead be an array which specifies not only the dimension of a `"S=3/2"`
-Index, but also additional subspace structure it has corresponding to quantum
-numbers.
-
-After defining this `space` function, you can just write code like:
-
-```julia
-using ITensors, ITensorMPS
-s = siteind("S=3/2")
-```
-
-to obtain a single `"S=3/2"` Index, or write code like
-
-```julia
-using ITensors, ITensorMPS
-N = 100
-sites = siteinds("S=3/2",N)
-```
-
-to obtain an array of N `"S=3/2"` indices. The custom `space` function
-will be used to determine the dimension of these indices, and the `siteind`
-or `siteinds` functions provided by ITensor will help with extra things like
-putting other Index tags that are conventional for site indices.
-
-**The op Function**
-
-The `op` function lets you define custom local operators associated
-to the physical degrees of freedom of your `SiteType`. Then for example
-you can use indices carrying your custom tag with OpSum and the
-OpSum system will know how to automatically convert names of operators
-such as `"Sz"` or `"S+"` into ITensors so that it can make an actual MPO.
-
-In our example above, we defined this function for the case of the `"Sz"`
-operator as:
-
-```@example S32
-using ITensors, ITensorMPS
-ITensors.op(::OpName"Sz",::SiteType"S=3/2") =
- [+3/2 0 0 0
- 0 +1/2 0 0
- 0 0 -1/2 0
- 0 0 0 -3/2]
-```
-
-As you can see, the function is passed two objects: an `OpName` and a `SiteType`.
-The strings `"Sz"` and `"S=3/2"` are also part of the type of these objects, and
-have the meaning of which operator name we are defining and which site type these
-operators are defined for.
-
-The body of this overload of `ITensors.op` constructs and returns a Julia matrix
-which gives the matrix elements of the operator we are defining.
-
-Once this function is defined, and if you have an Index such as
-
-```@example S32; continued = true
-s = Index(4,"S=3/2")
-```
-
-then, for example, you can get the `"Sz"` operator for this Index
-and print it out by doing:
-
-```@example S32
-using ITensors, ITensorMPS
-Sz = op("Sz",s)
-println(Sz)
-```
-
-Again, through the magic of the `SiteType`
-system, the ITensor library takes your Index, reads off its tags,
-notices that one of them is `"S=3/2"`, and converts this into the type
-`SiteType"S=3/2"` in order to call the specialized function `ITensors.op` defined above.
-
-You can use the `op` function yourself with a set of site indices created from
-the `siteinds` function like this:
-
-```julia
-using ITensors, ITensorMPS
-N = 100
-sites = siteinds("S=3/2",N)
-Sz1 = op("Sz",sites[1])
-Sp3 = op("S+",sites[3])
-```
-
-Alternatively, you can write the lines of code above in the style
-of `Sz1 = op("Sz",sites,1)`.
-
-This same `op` function is used inside of OpSum (formerly called AutoMPO)
-when it converts its input into
-an actual MPO. So by defining custom operator names you can pass any of these
-operator names into OpSum and it will know how to use these operators.
-
-**Further Steps**
-
-See how the built-in site types are defined inside the ITensor library:
-* [S=1/2 sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/spinhalf.jl) - Dimension 2 local Hilbert space. Similar to the `"Qubit"` site type, shares many of the same operator definitions.
-* [Qubit sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/qubit.jl) - Dimension 2 local Hilbert space. Similar to the `"S=1/2"` site type, shares many of the same operator definitions.
-* [S=1 sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/spinone.jl) - Dimension 3 local Hilbert space.
-* [Fermion sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/fermion.jl) - Dimension 2 local Hilbert space. Spinless fermion site type.
-* [Electron sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/electron.jl) - Dimension 4 local Hilbert space. Spinfull fermion site type.
-* [tJ sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/tj.jl) - Dimension 3 local Hilbert space. Spinfull fermion site type but without a doubly occupied state in the Hilbert space.
-* [Boson sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/boson.jl) - General d-dimensional local Hilbert space. Shares the same operator definitions as the `"Qudit"` site type.
-* [Qudit sites](https://github.com/ITensor/ITensors.jl/blob/main/src/lib/SiteTypes/src/sitetypes/qudit.jl) - General d-dimensional local Hilbert space. Generalization of the `"Qubit"` site type, shares the same operator definitions as the ``Boson`` site type.
-
-
-## Make a Custom Local Hilbert Space with QNs
-
-In the previous example above, we discussed the basic,
-minimal code needed to define a custom local Hilbert space, using the example
-of a ``S=3/2`` spin Hilbert space. In those examples, the `space` function
-defining the vector space of a ``S=3/2`` spin only provides the dimension of
-the space. But the Hilbert space of a ``S=3/2`` spin has additional structure, which
-is that each of its four subspaces (each of dimension 1) can be labeled by
-a different ``S^z`` quantum number.
-
-In this code formula we will include this extra quantum information in the
-definition of the space of a ``S=3/2`` spin.
-
-**Code Preview**
-
-First let's see the minimal code needed to add the option for including
-quantum numbers of our ``S=3/2`` site type, then we will discuss what each part of
-the code is doing.
-
-```julia
-using ITensors, ITensorMPS
-
-function ITensors.space(::SiteType"S=3/2";
- conserve_qns=false)
- if conserve_qns
- return [QN("Sz",3)=>1,QN("Sz",1)=>1,
- QN("Sz",-1)=>1,QN("Sz",-3)=>1]
- end
- return 4
-end
-
-ITensors.op(::OpName"Sz",::SiteType"S=3/2") =
- [+3/2 0 0 0
- 0 +1/2 0 0
- 0 0 -1/2 0
- 0 0 0 -3/2]
-
-ITensors.op(::OpName"S+",::SiteType"S=3/2") =
- [0 √3 0 0
- 0 0 2 0
- 0 0 0 √3
- 0 0 0 0]
-
-ITensors.op(::OpName"S-",::SiteType"S=3/2") =
- [0 0 0 0
- √3 0 0 0
- 0 2 0 0
- 0 0 √3 0]
-
-
-```
-
-Now let's look at each part of the code above.
-
-**The space function**
-
-In the previous code example above, we discussed
-that the function `space` tells the ITensor library the basic information about how
-to construct an Index associated with a special Index tag, in this case the tag `"S=3/2"`.
-As in that code formula, if the user does not request that quantum numbers be included
-(the case `conserve_qns=false`) then all that the `space` function returns is the number
-4, indicating that a `"S=3/2"` Index should be of dimension 4.
-
-But if the `conserve_qns` keyword argument gets set to `true`, the `space` function we
-defined above returns an array of `QN=>Int` pairs. (The notation `a=>b` in Julia constructs
-a `Pair` object.) Each pair in the array denotes a subspace.
-The `QN` part of each pair says what quantum number the subspace has, and the integer following
-it indicates the dimension of the subspace.
-
-After defining the `space` function this way, you can write code like:
-
-```julia
-using ITensors, ITensorMPS
-s = siteind("S=3/2"; conserve_qns=true)
-```
-
-to obtain a single `"S=3/2"` Index which carries quantum number information.
-The `siteind` function built into ITensor relies on your custom `space` function
-to ask how to construct a `"S=3/2"` Index but also includes some other Index tags
-which are conventional for all site indices.
-
-You can now also call code like:
-
-```julia
-using ITensors, ITensorMPS
-N = 100
-sites = siteinds("S=3/2",N; conserve_qns=true)
-```
-
-to obtain an array of N `"S=3/2"` indices which carry quantum numbers.
-
-**The op Function in the Quantum Number Case**
-
-Note that the `op` function overloads are exactly the same as for the
-more basic case of defining an `"S=3/2"` Index type that does not carry
-quantum numbers. There is no need to upgrade any of the `op` functions
-for the QN-conserving case.
-The reason is that all QN, block-sparse information
-about an ITensor is deduced from the indices of the tensor, and setting elements
-of such tensors does not require any other special code.
-
-However, only operators which have a well-defined QN flux---meaning they always
-change the quantum number of a state they act on by a well-defined amount---can
-be used in practice in the case of QN conservation. Attempting to build an operator, or any ITensor,
-without a well-defined QN flux out of QN-conserving indices will result in a run time error.
-An example of an operator that would lead to such an error would be the "Sx" spin operator
-since it alternately increases ``S^z`` or decreases ``S^z`` depending on the state it acts
-on, thus it does not have a well-defined QN flux. But it is perfectly fine to define an
-`op` overload for the "Sx" operator and to make this operator when working with dense,
-non-QN-conserving ITensors or when ``S^z`` is not conserved.
-
-
diff --git a/docs/src/examples/combiner_itensor.png b/docs/src/examples/combiner_itensor.png
deleted file mode 100644
index b52357410e64c24b59d5a72beb3047e7c531c74a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 62978
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