Skip to content

Commit a8e5bf5

Browse files
authored
Merge branch 'main' into ITensors_fix_eigen_perturbation
2 parents 223a550 + 791f690 commit a8e5bf5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1491
-37
lines changed

ITensorGPU/test/test_dmrg.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ end
9393
dmrg_params = (; nsweeps=4, maxdim=10, cutoff=1e-8, noise=1e-8, outputlevel=0)
9494
observer = DMRGObserver(["Z"], s; energy_tol=1e-4, minsweeps=10)
9595
E, ψ = dmrg(H, ψ0; observer=observer, dmrg_params...)
96-
@test expect(ψ, "Z") observer.measurements["Z"][end]
96+
@test expect(ψ, "Z") observer.measurements["Z"][end] rtol =
97+
10 * sqrt(eps(real(ITensors.scalartype(ψ0))))
9798
@test correlation_matrix(ψ, "Z", "Z") correlation_matrix(cpu(ψ), "Z", "Z")
9899
end
99100

NDTensors/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
1212
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
1313
EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
1414
FLoops = "cc61a311-1640-44b5-9fba-1b764f453329"
15+
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
1516
Folds = "41a02a25-b8f0-4f67-bc48-60067656b558"
1617
Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
1718
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
1819
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
20+
HalfIntegers = "f0d1745a-41c9-11e9-1dd9-e5d34d218721"
1921
InlineStrings = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
2022
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2123
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
@@ -52,10 +54,12 @@ Compat = "4.9"
5254
Dictionaries = "0.3.5"
5355
EllipsisNotation = "1.8"
5456
FLoops = "0.2.1"
57+
FillArrays = "1"
5558
Folds = "0.2.8"
5659
Functors = "0.2, 0.3, 0.4"
5760
GPUArraysCore = "0.1"
5861
HDF5 = "0.14, 0.15, 0.16, 0.17"
62+
HalfIntegers = "1"
5963
InlineStrings = "1"
6064
LinearAlgebra = "1.6"
6165
MappedArrays = "0.4"

NDTensors/src/NDTensors.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ for lib in [
2323
:AlgorithmSelection,
2424
:AllocateData,
2525
:BaseExtensions,
26+
:UnspecifiedTypes,
2627
:SetParameters,
2728
:BroadcastMapConversion,
2829
:Unwrap,
@@ -35,8 +36,10 @@ for lib in [
3536
:BlockSparseArrays,
3637
:NamedDimsArrays,
3738
:SmallVectors,
39+
:Sectors,
3840
:SortedSets,
3941
:TagSets,
42+
:UnallocatedArrays,
4043
]
4144
include("lib/$(lib)/src/$(lib).jl")
4245
@eval using .$lib: $lib
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module Sectors
2+
3+
include("abstractcategory.jl")
4+
include("group_definitions.jl")
5+
include("category_definitions.jl")
6+
7+
include("namedtuple_operations.jl")
8+
include("category_product.jl")
9+
10+
end
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
abstract type AbstractCategory end
2+
3+
label(c::AbstractCategory) = error("method `label` not defined for type $(typeof(c))")
4+
5+
function dimension(c::AbstractCategory)
6+
return error("method `dimension` not defined for type $(typeof(c))")
7+
end
8+
9+
function label_fusion_rule(::Type{C}, l1, l2) where {C<:AbstractCategory}
10+
return error("label_fusion_rule not defined for type $(C)")
11+
end
12+
13+
function fusion_rule(c1::AbstractCategory, c2::AbstractCategory)
14+
C = typeof(c1)
15+
return [C(d) for d in label_fusion_rule(C, label(c1), label(c2))]
16+
end
17+
18+
(c1::AbstractCategory, c2::AbstractCategory) = fusion_rule(c1, c2)
19+
20+
Base.:(*)(s1::AbstractCategory, s2::AbstractCategory) = (s1, s2)
21+
22+
(a::AbstractCategory, b::AbstractCategory) = [a, b]
23+
(v::Vector{<:AbstractCategory}, b::AbstractCategory) = vcat(v, b)
24+
(a::AbstractCategory, v::Vector{<:AbstractCategory}) = vcat(a, v)
25+
26+
function Base.show(io::IO, q::Vector{<:AbstractCategory})
27+
(length(q) <= 1) && print(io, "[")
28+
symbol = ""
29+
for l in q
30+
print(io, symbol, l)
31+
symbol = ""
32+
end
33+
return (length(q) <= 1) && print(io, "]")
34+
end
35+
36+
function trivial(::Type{C}) where {C<:AbstractCategory}
37+
return error("method `trivial` not defined for type $C")
38+
end
39+
40+
istrivial(C::AbstractCategory) = (C == trivial(typeof(C)))
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import HalfIntegers: Half
2+
3+
#
4+
# Quantum 'group' su2ₖ
5+
#
6+
7+
struct su2{k} <: AbstractCategory
8+
j::Half{Int}
9+
end
10+
11+
label(s::su2) = s.j
12+
13+
level(s::su2{k}) where {k} = k
14+
15+
trivial(::Type{su2{k}}) where {k} = su2{k}(0)
16+
17+
function label_fusion_rule(::Type{su2{k}}, j1, j2) where {k}
18+
return abs(j1 - j2):min(k - j1 - j2, j1 + j2)
19+
end
20+
21+
#
22+
# Fibonacci category
23+
#
24+
# (same fusion rules as subcategory {0,1} of su2{3})
25+
#
26+
27+
struct Fib <: AbstractCategory
28+
l::Int
29+
end
30+
31+
function Fib(s::AbstractString)
32+
if s == "1"
33+
return Fib(0)
34+
elseif s == "τ"
35+
return Fib(1)
36+
end
37+
return error("Unrecognized input \"$s\" to Fib constructor")
38+
end
39+
40+
label(f::Fib) = f.l
41+
42+
trivial(::Type{Fib}) = Fib(0)
43+
44+
dimension(f::Fib) = istrivial(f) ? 1 : ((1 + 5) / 2)
45+
46+
# Fusion rules identical to su2₃
47+
label_fusion_rule(::Type{Fib}, l1, l2) = label_fusion_rule(su2{3}, l1, l2)
48+
49+
label_to_str(f::Fib) = istrivial(f) ? "1" : "τ"
50+
51+
function Base.show(io::IO, f::Fib)
52+
return print(io, "Fib(", label_to_str(f), ")")
53+
end
54+
55+
#
56+
# Ising category
57+
#
58+
# (same fusion rules as su2{2})
59+
#
60+
61+
struct Ising <: AbstractCategory
62+
l::Half{Int}
63+
end
64+
65+
function Ising(s::AbstractString)
66+
for (a, v) in enumerate(("1", "σ", "ψ"))
67+
(v == s) && return Ising((a - 1)//2)
68+
end
69+
return error("Unrecognized input \"$s\" to Ising constructor")
70+
end
71+
72+
label(i::Ising) = i.l
73+
74+
trivial(::Type{Ising}) = Ising(0)
75+
76+
dimension(i::Ising) = (label(i) == 1//2) ? 2 : 1
77+
78+
# Fusion rules identical to su2₂
79+
label_fusion_rule(::Type{Ising}, l1, l2) = label_fusion_rule(su2{2}, l1, l2)
80+
81+
label_to_str(i::Ising) = ("1", "σ", "ψ")[Int(2 * label(i) + 1)]
82+
83+
function Base.show(io::IO, f::Ising)
84+
return print(io, "Ising(", label_to_str(f), ")")
85+
end
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
2+
struct CategoryProduct{Categories} <: AbstractCategory
3+
cats::Categories
4+
global _CategoryProduct(l) = new{typeof(l)}(l)
5+
end
6+
7+
CategoryProduct(c::CategoryProduct) = _CategoryProduct(categories(c))
8+
9+
categories(s::CategoryProduct) = s.cats
10+
11+
Base.isempty(S::CategoryProduct) = isempty(categories(S))
12+
Base.length(S::CategoryProduct) = length(categories(S))
13+
Base.getindex(S::CategoryProduct, args...) = getindex(categories(S), args...)
14+
15+
function fusion_rule(s1::CategoryProduct, s2::CategoryProduct)
16+
return [
17+
CategoryProduct(l) for l in categories_fusion_rule(categories(s1), categories(s2))
18+
]
19+
end
20+
21+
function Base.:(==)(A::CategoryProduct, B::CategoryProduct)
22+
return categories_equal(categories(A), categories(B))
23+
end
24+
25+
function Base.show(io::IO, s::CategoryProduct)
26+
(length(s) < 2) && print(io, "sector")
27+
print(io, "(")
28+
symbol = ""
29+
for p in pairs(categories(s))
30+
print(io, symbol)
31+
category_show(io, p[1], p[2])
32+
symbol = " × "
33+
end
34+
return print(io, ")")
35+
end
36+
37+
category_show(io::IO, k, v) = print(io, v)
38+
39+
category_show(io::IO, k::Symbol, v) = print(io, "($k=$v,)")
40+
41+
×(c1::AbstractCategory, c2::AbstractCategory) = ×(CategoryProduct(c1), CategoryProduct(c2))
42+
function ×(p1::CategoryProduct, p2::CategoryProduct)
43+
return CategoryProduct(categories_product(categories(p1), categories(p2)))
44+
end
45+
46+
categories_product(l1::NamedTuple, l2::NamedTuple) = union_keys(l1, l2)
47+
48+
categories_product(l1::Tuple, l2::Tuple) = (l1..., l2...)
49+
50+
×(nt1::NamedTuple, nt2::NamedTuple) = ×(CategoryProduct(nt1), CategoryProduct(nt2))
51+
×(c1::NamedTuple, c2::AbstractCategory) = ×(CategoryProduct(c1), CategoryProduct(c2))
52+
×(c1::AbstractCategory, c2::NamedTuple) = ×(CategoryProduct(c1), CategoryProduct(c2))
53+
54+
#
55+
# Dictionary-like implementation
56+
#
57+
58+
function CategoryProduct(nt::NamedTuple)
59+
categories = sort_keys(nt)
60+
return _CategoryProduct(categories)
61+
end
62+
63+
CategoryProduct(; kws...) = CategoryProduct((; kws...))
64+
65+
function CategoryProduct(pairs::Pair...)
66+
keys = ntuple(n -> Symbol(pairs[n][1]), length(pairs))
67+
vals = ntuple(n -> pairs[n][2], length(pairs))
68+
return CategoryProduct(NamedTuple{keys}(vals))
69+
end
70+
71+
function categories_fusion_rule(A::NamedTuple, B::NamedTuple)
72+
qs = [A]
73+
for (la, lb) in zip(pairs(intersect_keys(A, B)), pairs(intersect_keys(B, A)))
74+
@assert la[1] == lb[1]
75+
fused_vals = (la[2], lb[2])
76+
qs = [union_keys((; la[1] => v), q) for v in fused_vals for q in qs]
77+
end
78+
# Include sectors of B not in A
79+
qs = [union_keys(q, B) for q in qs]
80+
return qs
81+
end
82+
83+
function categories_equal(A::NamedTuple, B::NamedTuple)
84+
common_categories = zip(pairs(intersect_keys(A, B)), pairs(intersect_keys(B, A)))
85+
common_categories_match = all(nl -> (nl[1] == nl[2]), common_categories)
86+
unique_categories_zero = all(l -> istrivial(l), symdiff_keys(A, B))
87+
return common_categories_match && unique_categories_zero
88+
end
89+
90+
#
91+
# Ordered implementation
92+
#
93+
94+
CategoryProduct(t::Tuple) = _CategoryProduct(t)
95+
CategoryProduct(cats::AbstractCategory...) = CategoryProduct((cats...,))
96+
97+
categories_equal(o1::Tuple, o2::Tuple) = (o1 == o2)
98+
99+
function categories_fusion_rule(o1::Tuple, o2::Tuple)
100+
N = length(o1)
101+
length(o2) == N ||
102+
throw(DimensionMismatch("Ordered CategoryProduct must have same size in ⊗"))
103+
os = [o1]
104+
replace(o, n, val) = ntuple(m -> (m == n) ? val : o[m], length(o))
105+
for n in 1:N
106+
os = [replace(o, n, f) for f in (o1[n], o2[n]) for o in os]
107+
end
108+
return os
109+
end
110+
111+
sector(args...; kws...) = CategoryProduct(args...; kws...)

0 commit comments

Comments
 (0)