Skip to content

Commit 09371e7

Browse files
committed
Update exp code to take input index ordering literally
1 parent f1c0378 commit 09371e7

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

src/tensor_operations/matrix_algebra.jl

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ function exp(A::ITensor, Linds, Rinds; ishermitian=false)
4949
ndims(A) != NL + NR &&
5050
error("Number of left and right indices must add up to total number of indices")
5151

52-
# Permute Lis, Ris to be in same order as on A
53-
Lis = permute(commoninds(A, Linds), Linds)
54-
Ris = permute(commoninds(A, Rinds), Rinds)
52+
# Replace Linds and Rinds with index sets having
53+
# same id's but arrow directions as on A
54+
Linds = permute(commoninds(A, Linds), Linds)
55+
Rinds = permute(commoninds(A, Rinds), Rinds)
5556

5657
# Ensure indices have correct directions, QNs, etc.
57-
for (l, r) in zip(Lis, Ris)
58+
for (l, r) in zip(Linds, Rinds)
5859
if space(l) != space(r)
5960
error("In exp, indices must come in pairs with equal spaces.")
6061
end
@@ -66,25 +67,36 @@ function exp(A::ITensor, Linds, Rinds; ishermitian=false)
6667
# <fermions>
6768
auto_fermion_enabled = using_auto_fermion()
6869
if auto_fermion_enabled
69-
if all(j->dir(j)==Out, Lis)
70-
ordered_inds = [Lis..., reverse(Ris)...]
71-
elseif all(j->dir(j)==In, Lis)
72-
ordered_inds = [reverse(Ris)..., Lis...]
70+
# If fermionic, bring indices into i',j',..,dag(j),dag(i)
71+
# ordering with Out indices coming before In indices
72+
# Resulting tensor acts like a normal matrix (no extra signs
73+
# when taking powers A^n)
74+
if all(j->dir(j)==Out, Linds) && all(j->dir(j)==In, Rinds)
75+
ordered_inds = [Linds..., reverse(Rinds)...]
76+
elseif all(j->dir(j)==Out, Rinds) && all(j->dir(j)==In, Linds)
77+
ordered_inds = [Rinds..., reverse(Linds)...]
7378
else
74-
error("For fermionic exp, Linds must have same direction, dir.(Linds)=", dir.(Linds))
79+
error(
80+
"For fermionic exp, Linds and Rinds must have same directions within each set. Got dir.(Linds)=",
81+
dir.(Linds),
82+
", dir.(Rinds)=",
83+
dir.(Rinds),
84+
)
7585
end
7686
A = permute(A, ordered_inds)
87+
# A^n now sign free, ok to temporarily disable fermion system
7788
disable_auto_fermion()
7889
end
7990

80-
CL = combiner(Lis...; dir=Out)
81-
CR = combiner(Ris...; dir=In)
91+
CL = combiner(Linds...; dir=Out)
92+
CR = combiner(Rinds...; dir=In)
8293
AC = (A * CR) * CL
8394
expAT = ishermitian ? exp(Hermitian(tensor(AC))) : exp(tensor(AC))
8495
expA = (itensor(expAT) * dag(CR)) * dag(CL)
8596

8697
# <fermions>
8798
if auto_fermion_enabled
99+
# Ensure expA indices in "matrix" form before re-enabling fermion system
88100
expA = permute(expA, ordered_inds)
89101
enable_auto_fermion()
90102
end
@@ -94,7 +106,7 @@ end
94106

95107
function exp(A::ITensor; kwargs...)
96108
Ris = filterinds(A; plev=0)
97-
Lis = Ris'
109+
Lis = dag.(prime.(Ris))
98110
return exp(A, Lis, Ris; kwargs...)
99111
end
100112

test/base/test_fermions.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,15 @@ using ITensors.SiteTypes: op, siteind, siteinds
792792
# Permute and test again
793793
id_tensor = permute(id_tensor, s[2], s[1], s[2]', s[1]')
794794
@test id_tensor exp(0.0 * id_tensor)
795+
796+
# Explicitly passing indices in different, valid orders
797+
@test id_tensor exp(0.0 * id_tensor, (s[1]', s[2]'), (dag(s[1]), dag(s[2])))
798+
@test id_tensor exp(0.0 * id_tensor, (s[2]', s[1]'), (dag(s[2]), dag(s[1])))
799+
@test id_tensor exp(0.0 * id_tensor, (dag(s[1]), dag(s[2])), (s[1]', s[2]'))
800+
@test id_tensor exp(0.0 * id_tensor, (dag(s[2]), dag(s[1])), (s[2]', s[1]'))
801+
802+
# Check wrong index ordering fails (i.e. we are actually paying attention to it)
803+
@test norm(id_tensor - exp(0.0 * id_tensor, (dag(s[1]), dag(s[2])), (s[2]', s[1]'))) > 1
795804
end
796805

797806
ITensors.disable_auto_fermion()

0 commit comments

Comments
 (0)