Skip to content

Commit 4efbdae

Browse files
committed
Merge branch 'main' of github.com:ITensor/ITensors.jl into main
2 parents 0ff6cbe + 0247fc8 commit 4efbdae

19 files changed

+266
-213
lines changed

docs/src/ITensorType.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ swapinds(::ITensor, ::Any...)
116116

117117
```@docs
118118
*(::ITensor, ::ITensor)
119+
dag(T::ITensor; kwargs...)
119120
exp(::ITensor, ::Any, ::Any)
120121
nullspace(::ITensor, ::Any...)
121122
```

docs/src/MPSandMPO.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ prime(::typeof(linkinds), ::ITensors.AbstractMPS)
7272
prime(::typeof(siteinds), ::typeof(commoninds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS)
7373
prime(::typeof(siteinds), ::typeof(uniqueinds), ::ITensors.AbstractMPS, ::ITensors.AbstractMPS)
7474
75+
swapprime(::ITensors.AbstractMPS, args...; kwargs...)
76+
7577
setprime(::ITensors.AbstractMPS)
7678
setprime(::typeof(siteinds), ::ITensors.AbstractMPS)
7779
setprime(::typeof(linkinds), ::ITensors.AbstractMPS)

docs/src/examples/MPSandMPO.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ See below for a visual depiction of what the above code is doing:
119119
## Expected Value of Local Operators
120120

121121
When using an MPS to represent a quantum wavefunction ``|\psi\rangle``
122-
a common operation is computed the expected value ``\langle\psi|\hat{A}_j|\psi\rangle``
122+
a common operation is computing the expected value ``\langle\psi|\hat{A}_j|\psi\rangle``
123123
of a local operator ``\hat{A}_j`` acting on site ``j``. This can be accomplished
124124
efficiently and conveniently using the [`expect`](@ref) function as:
125125

@@ -152,6 +152,21 @@ end
152152

153153
![](mps_expect.png)
154154

155+
## Expected Values of MPO Operators
156+
157+
When using an MPS to represent a quantum wavefunction ``|\psi\rangle``
158+
another common operation is computing the expected value ``\langle\psi|W|\psi\rangle``
159+
of an operator ``W`` which is represented as a matrix product operator (MPO) tensor network.
160+
A key example could be the Hamiltonian defining a quantum system.
161+
162+
Given an MPO `W` and an MPS `psi`, you can compute ``\langle\psi|W|\psi\rangle``
163+
by using the function `inner` as follows:
164+
```julia
165+
ex_W = inner(psi,W,psi)
166+
```
167+
which will return a scalar that may be either real or complex, depending on the properties of
168+
`psi` and `W`.
169+
155170
## Computing Correlation Functions
156171

157172
In addition to expected values of local operators

docs/src/examples/Physics.md

Lines changed: 155 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,160 @@
11
# Physics (SiteType) System Examples
22

3+
## Making a Custom op Definition
4+
5+
The function `op` is used to obtain operators defined for a
6+
given "site type". ITensor includes pre-defined site types such
7+
as "S=1/2", "S=1", "Electron" and others. Or you can define your own site type
8+
as discussed in detail in the code examples further below.
9+
10+
**Extending op Function Definitions**
11+
12+
Perhaps the most common part of the site type system one wishes to extend
13+
are the various `op` or `op!` function overloads which allow code like
14+
15+
```julia
16+
s = siteind("S=1/2")
17+
Sz = op("Sz",s)
18+
```
19+
20+
to automatically create the ``S^z`` operator for an Index `s` based on the
21+
`"S=1/2"` tag it carries. A major reason to define such `op` overloads
22+
is to allow the OpSum system to recognize new operator names, as
23+
discussed more below.
24+
25+
Let's see how to introduce a new operator name into the ITensor site type
26+
system for this existing site type of `"S=1/2"`. The operator we will
27+
introduce is the projector onto the up spin state ``P_\uparrow`` which
28+
we will denote with the string `"Pup"`.
29+
30+
As a matrix acting on the space ``\{ |\!\uparrow\rangle, |\!\downarrow\rangle \}``,
31+
the ``P_\uparrow`` operator is given by
32+
33+
```math
34+
\begin{aligned}
35+
36+
P_\uparrow &=
37+
\begin{bmatrix}
38+
1 & 0 \\
39+
0 & 0 \\
40+
\end{bmatrix}
41+
42+
\end{aligned}
43+
```
44+
45+
To add this operator to the ITensor `op` system, we just need to introduce the following
46+
code
47+
48+
```julia
49+
using ITensors
50+
51+
ITensors.op(::OpName"Pup",::SiteType"S=1/2") =
52+
[1 0
53+
0 0]
54+
```
55+
56+
This code can be defined anywhere, such as in your own personal application code and does
57+
not have to be put into the ITensor library source code.
58+
59+
Note that we have to name the function `ITensors.op` and not just `op` so that it overloads
60+
other functions of the name `op` inside the ITensors module.
61+
62+
Having defined the above code, we can now do things like
63+
64+
```julia
65+
s = siteind("S=1/2")
66+
Pup = op("Pup",s)
67+
```
68+
69+
to obtain the `"Pup"` operator for our `"S=1/2"` Index `s`. Or we can do a similar
70+
thing for an array of site indices:
71+
72+
```julia
73+
N = 40
74+
s = siteinds("S=1/2",N)
75+
Pup1 = op("Pup",s[1])
76+
Pup3 = op("Pup",s[3])
77+
```
78+
79+
Note that for the `"Qudit"`/`"Boson"` site types, you have to define your overload
80+
of `op` with the dimension of the local Hilbert space, for example:
81+
```julia
82+
using ITensors
83+
84+
function ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int)
85+
o = zeros(d, d)
86+
o[1, 1] = 1
87+
return o
88+
end
89+
```
90+
Alternatively you could use Julia's [array comprehension](https://docs.julialang.org/en/v1/manual/arrays/#man-comprehensions) syntax:
91+
```julia
92+
ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) =
93+
[(i == j == 1) ? 1.0 : 0.0 for i in 1:d, j in 1:d]
94+
```
95+
96+
**Using Custom Operators in OpSum**
97+
98+
A key use of these `op` system extensions is allowing additional operator names to
99+
be recognized by the OpSum system for constructing matrix product operator (MPO)
100+
tensor networks. With the code above defining the `"Pup"` operator, we are now
101+
allowed to use this operator name in any OpSum code involving `"S=1/2"` site
102+
indices.
103+
104+
For example, we could now make an OpSum involving our custom operator such as:
105+
106+
```julia
107+
N = 100
108+
sites = siteinds("S=1/2",N)
109+
os = OpSum()
110+
for n=1:N
111+
os += "Pup",n
112+
end
113+
P = MPO(os,sites)
114+
```
115+
116+
This code makes an MPO `P` which is just the sum of a spin-up projection operator
117+
acting on every site.
118+
119+
120+
## Making a Custom state Definition
121+
122+
The function `state` is used to define states (single-site wavefunctions)
123+
that sites can be in. For example, the "Qubit" site type includes
124+
definitions for the "0" and "1" states as well as the "+" (eigenstate of X operator)
125+
state. The "S=1/2" site type includes definitions for the "Up" and "Dn" (down) states.
126+
127+
Say we want to define a new state for the "Electron" site type called "+", which has
128+
the meaning of one electron with its spin in the +X direction. First let's review
129+
the existing state definitions:
130+
```julia
131+
ITensors.state(::StateName"Emp", ::SiteType"Electron") = [1.0, 0, 0, 0]
132+
ITensors.state(::StateName"Up", ::SiteType"Electron") = [0.0, 1, 0, 0]
133+
ITensors.state(::StateName"Dn", ::SiteType"Electron") = [0.0, 0, 1, 0]
134+
ITensors.state(::StateName"UpDn", ::SiteType"Electron") = [0.0, 0, 0, 1]
135+
```
136+
As we can see, the four settings of an "Electron" index correspond to the states
137+
``|0\rangle, |\uparrow\rangle, |\downarrow\rangle, |\uparrow\downarrow\rangle``.
138+
139+
So we can define our new state "+" as follows:
140+
```julia
141+
ITensors.state(::StateName"+", ::SiteType"Electron") = [0, 1/sqrt(2), 1/sqrt(2), 0]
142+
```
143+
which makes the state
144+
```math
145+
|+\rangle = \frac{1}{\sqrt{2}} |\uparrow\rangle + \frac{1}{\sqrt{2}} |\downarrow\rangle
146+
```
147+
148+
Having defined this overload of `state`, if we have an Index of type "Electron"
149+
we can obtain our new state for it by doing
150+
```julia
151+
s = siteind("Electron")
152+
plus = state("+",s)
153+
```
154+
We can also use this new state definition in other ITensor features such as
155+
the MPS constructor taking an array of state names.
156+
157+
3158
## Make a Custom Local Hilbert Space / Physical Degree of Freedom
4159

5160
ITensor provides support for a range of common local Hilbert space types,
@@ -336,126 +491,3 @@ on, thus it does not have a well-defined QN flux. But it is perfectly fine to de
336491
non-QN-conserving ITensors or when ``S^z`` is not conserved.
337492

338493

339-
## Extending an Existing Local Hilbert Space
340-
341-
In the two previous examples above, we discussed the basics
342-
of how custom local Hilbert spaces a.k.a. site types can be defined from
343-
scratch in ITensor. However, there are cases where a custom site type is
344-
already designed for you, such as the site types `"S=1/2"`, `"S=1"`,
345-
`"Fermion"`, `"Electron"` and others included with ITensor.
346-
347-
A nice feature of the ITensor `SiteType` system is that you can arbitrarily
348-
extend operator and other definitions, even of existing `SiteTypes` created
349-
in other code or by someone else.
350-
351-
**Extending op Function Definitions**
352-
353-
Perhaps the most common part of the `SiteType` system one wishes to extend
354-
are the various `op` or `op!` function overloads which allow code like
355-
356-
```julia
357-
s = siteind("S=1/2")
358-
Sz = op("Sz",s)
359-
```
360-
361-
to automatically create the ``S^z`` operator for an Index `s` based on the
362-
`"S=1/2"` tag it carries. A major reason to define such `op` overloads
363-
is to allow the OpSum (formerly AutoMPO) system to recognize new operator names, as
364-
discussed more below.
365-
366-
Let's see how to introduce a new operator name into the ITensor `SiteType`
367-
system for this existing site type of `"S=1/2"`. The operator we will
368-
introduce is the projector onto the up spin state ``P_\uparrow`` which
369-
we will denote with the string `"Pup"`.
370-
371-
As a matrix acting on the space ``\{ |\!\uparrow\rangle, |\!\downarrow\rangle \}``,
372-
the ``P_\uparrow`` operator is given by
373-
374-
```math
375-
\begin{aligned}
376-
377-
P_\uparrow &=
378-
\begin{bmatrix}
379-
1 & 0 \\
380-
0 & 0 \\
381-
\end{bmatrix}
382-
383-
\end{aligned}
384-
```
385-
386-
To add this operator to the ITensor `op` system, we just need to introduce the following
387-
code
388-
389-
```julia
390-
using ITensors
391-
392-
ITensors.op(::OpName"Pup",::SiteType"S=1/2") =
393-
[1 0
394-
0 0]
395-
```
396-
397-
This code can be defined anywhere, such as in your own personal application code and does
398-
not have to be put into the ITensor library source code.
399-
400-
Note that we have to name the function `ITensors.op!` and not just `op!` so that it overloads
401-
other functions of the name `op!` inside the ITensors module.
402-
403-
Having defined the above code, we can now do things like
404-
405-
```julia
406-
s = siteind("S=1/2")
407-
Pup = op("Pup",s)
408-
```
409-
410-
to obtain the `"Pup"` operator for our `"S=1/2"` Index `s`. Or we can do a similar
411-
thing for an array of site indices:
412-
413-
```julia
414-
N = 40
415-
s = siteinds("S=1/2",N)
416-
Pup1 = op("Pup",s[1])
417-
Pup3 = op("Pup",s[3])
418-
```
419-
420-
Note that for the `"Qudit"`/`"Boson"` site types, you have to define your overload
421-
of `op` with the dimension of the local Hilbert space, for example:
422-
```julia
423-
using ITensors
424-
425-
function ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int)
426-
o = zeros(d, d)
427-
o[1, 1] = 1
428-
return o
429-
end
430-
```
431-
Alternatively you could use Julia's [array comprehension](https://docs.julialang.org/en/v1/manual/arrays/#man-comprehensions) syntax:
432-
```julia
433-
ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) =
434-
[(i == j == 1) ? 1.0 : 0.0 for i in 1:d, j in 1:d]
435-
```
436-
437-
**Using Custom Operators in OpSum (AutoMPO)**
438-
439-
A key use of these `op` system extensions is allowing additional operator names to
440-
be recognized by the OpSum (formerly AutoMPO) system for constructing matrix product operator (MPO)
441-
tensor networks. With the code above defining the `"Pup"` operator, we are now
442-
allowed to use this operator name in any OpSum code involving `"S=1/2"` site
443-
indices.
444-
445-
For example, we could now make an OpSum involving our custom operator such as:
446-
447-
```julia
448-
N = 100
449-
sites = siteinds("S=1/2",N)
450-
ampo = OpSum()
451-
for n=1:N
452-
ampo += "Pup",n
453-
end
454-
P = MPO(ampo,sites)
455-
```
456-
457-
This code makes an MPO `P` which is just the sum of a spin-up projection operator
458-
acting on every site.
459-
460-
461-

examples/TBLIS/1d_heisenberg.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ let
1111

1212
N = 100
1313
sites = siteinds("S=1", N)
14-
ampo = OpSum()
14+
os = OpSum()
1515
for j in 1:(N - 1)
16-
ampo += 0.5, "S+", j, "S-", j + 1
17-
ampo += 0.5, "S-", j, "S+", j + 1
18-
ampo += "Sz", j, "Sz", j + 1
16+
os += 0.5, "S+", j, "S-", j + 1
17+
os += 0.5, "S-", j, "S+", j + 1
18+
os += "Sz", j, "Sz", j + 1
1919
end
20-
H = MPO(ampo, sites)
20+
H = MPO(os, sites)
2121
psi0 = randomMPS(sites, 10)
2222

2323
nsweeps = 6

examples/dmrg/1d_heisenberg.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ let
1313
#sites = siteinds("S=1/2",N)
1414

1515
# Input operator terms which define a Hamiltonian
16-
ampo = OpSum()
16+
os = OpSum()
1717
for j in 1:(N - 1)
18-
ampo += "Sz", j, "Sz", j + 1
19-
ampo += 0.5, "S+", j, "S-", j + 1
20-
ampo += 0.5, "S-", j, "S+", j + 1
18+
os += "Sz", j, "Sz", j + 1
19+
os += 0.5, "S+", j, "S-", j + 1
20+
os += 0.5, "S-", j, "S+", j + 1
2121
end
2222
# Convert these terms to an MPO tensor network
23-
H = MPO(ampo, sites)
23+
H = MPO(os, sites)
2424

2525
# Create an initial random matrix product state
2626
psi0 = randomMPS(sites, 10)

examples/dmrg/1d_heisenberg_conserve_spin.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ let
1515

1616
sites = siteinds("S=1", N; conserve_qns=true)
1717

18-
ampo = OpSum()
18+
os = OpSum()
1919
for j in 1:(N - 1)
20-
ampo .+= 0.5, "S+", j, "S-", j + 1
21-
ampo .+= 0.5, "S-", j, "S+", j + 1
22-
ampo .+= "Sz", j, "Sz", j + 1
20+
os .+= 0.5, "S+", j, "S-", j + 1
21+
os .+= 0.5, "S-", j, "S+", j + 1
22+
os .+= "Sz", j, "Sz", j + 1
2323
end
24-
H = MPO(ampo, sites)
24+
H = MPO(os, sites)
2525

2626
state = [isodd(n) ? "Up" : "Dn" for n in 1:N]
2727
psi0 = randomMPS(sites, state, 10)

0 commit comments

Comments
 (0)