From 5c9334c765251c94a8c3fa702b131b58ea7fcd63 Mon Sep 17 00:00:00 2001 From: Miles Date: Wed, 17 Sep 2025 16:30:45 -0400 Subject: [PATCH 1/6] Initial fix of arrows for dual, HPSD fermionic matrix --- src/tensor_operations/matrix_decomposition.jl | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/tensor_operations/matrix_decomposition.jl b/src/tensor_operations/matrix_decomposition.jl index 4e2acecb86..7fa4f95b00 100644 --- a/src/tensor_operations/matrix_decomposition.jl +++ b/src/tensor_operations/matrix_decomposition.jl @@ -353,17 +353,23 @@ function eigen( end # + L_arrow_dir = Out if hasqns(A) && using_auto_fermion() - if !all(i -> dir(i) == Out, Lis) - error("With auto_fermion enabled, left inds in eigen must have Out arrows") - end - if !all(i -> dir(i) == In, Ris) - error("With auto_fermion enabled, right inds in eigen must have Out arrows") + # Make arrows of combined ITensor + # match those of index sets + # TODO: also support Out,Out and In,In cases? + # I.e. through a R_arrow_dir variable? + if all(i -> dir(i) == Out, Lis) && all(i -> dir(i) == In, Ris) + L_arrow_dir = Out + elseif all(i -> dir(i) == In, Lis) && all(i -> dir(i) == Out, Ris) + L_arrow_dir = In + else + error("With auto_fermion enabled, index sets in eigen must have all arrows the same, and opposite between the sets") end end - CL = combiner(Lis...; dir=Out, tags="CMB,left") - CR = combiner(dag(Ris)...; dir=Out, tags="CMB,right") + CL = combiner(Lis...; dir=L_arrow_dir, tags="CMB,left") + CR = combiner(dag(Ris)...; dir=L_arrow_dir, tags="CMB,right") AC = A * dag(CR) * CL From 64d554bda7f29ab962173c562fcb46b32add4a2e Mon Sep 17 00:00:00 2001 From: Miles Date: Thu, 18 Sep 2025 10:20:19 -0400 Subject: [PATCH 2/6] Format & remove comment --- src/tensor_operations/matrix_decomposition.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tensor_operations/matrix_decomposition.jl b/src/tensor_operations/matrix_decomposition.jl index 7fa4f95b00..50d061b023 100644 --- a/src/tensor_operations/matrix_decomposition.jl +++ b/src/tensor_operations/matrix_decomposition.jl @@ -355,16 +355,15 @@ function eigen( # L_arrow_dir = Out if hasqns(A) && using_auto_fermion() - # Make arrows of combined ITensor - # match those of index sets - # TODO: also support Out,Out and In,In cases? - # I.e. through a R_arrow_dir variable? + # Make arrows of combined ITensor match those of index sets if all(i -> dir(i) == Out, Lis) && all(i -> dir(i) == In, Ris) L_arrow_dir = Out elseif all(i -> dir(i) == In, Lis) && all(i -> dir(i) == Out, Ris) L_arrow_dir = In else - error("With auto_fermion enabled, index sets in eigen must have all arrows the same, and opposite between the sets") + error( + "With auto_fermion enabled, index sets in eigen must have all arrows the same, and opposite between the sets", + ) end end From 3e0a23e6e6606a4483d91c4b22bb506e019241da Mon Sep 17 00:00:00 2001 From: Miles Date: Thu, 18 Sep 2025 10:22:12 -0400 Subject: [PATCH 3/6] Add tests for both types of HPSD fermionic matrices --- test/base/test_decomp.jl | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/base/test_decomp.jl b/test/base/test_decomp.jl index 82850668db..88f78edc62 100644 --- a/test/base/test_decomp.jl +++ b/test/base/test_decomp.jl @@ -500,4 +500,46 @@ end @test norm(U * B - phi) < 1E-5 @test dim(commonind(U, B)) <= 4 end + + @testset "Eigen of Fermionic Matrices" begin + ITensors.enable_auto_fermion() + s = Index([QN("Nf", 0, -1)=>2, QN("Nf", 1, -1)=>2], "s,Site,Fermion") + t = Index([QN("Nf", 0, -1)=>2, QN("Nf", 1, -1)=>2], "t,Site,Fermion") + + # + # HPSD Operator (Out,In) case + # + M = random_itensor(s, dag(t)) + O = prime(M,s)*dag(M) + + @test dir(inds(O)[1]) == ITensors.Out + @test dir(inds(O)[2]) == ITensors.In + linds = [s'] + rinds = [dag(s)] + D_O, U = eigen(O, linds, rinds; ishermitian=true) + @test norm(prime(U)*D_O*dag(U)-O) < 1E-10 + @test all(>=(0.),diag(array(D_O))) + + println() + + # + # HPSD Dual operator (In,Out) case + # + # Make ρ out of two squared states + # to populate both blocks: (0,0) and (1,1) + ψ0 = random_itensor(t,s) + ρ0 = prime(dag(ψ0),s)*ψ0 + + ψ2 = random_itensor(QN("Nf",2,-1),t,s) + ρ2 = prime(dag(ψ2),s)*ψ2 + + ρ = ρ0/2 + ρ2/2 + @test dir(inds(ρ)[1]) == ITensors.In + @test dir(inds(ρ)[2]) == ITensors.Out + + D_ρ, U = eigen(ρ, [dag(s)'], [s]; ishermitian=true) + @test all(>=(0.),diag(array(D_ρ))) + @test norm(prime(U)*D_ρ*dag(U)-ρ) < 1E-10 + ITensors.disable_auto_fermion() + end end From 385bdda853c25e7703831b1541d5d118cfe5c3c8 Mon Sep 17 00:00:00 2001 From: Miles Date: Thu, 18 Sep 2025 10:22:56 -0400 Subject: [PATCH 4/6] Bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 5a790df5bb..4c9134a06e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ITensors" uuid = "9136182c-28ba-11e9-034c-db9fb085ebd5" authors = ["Matthew Fishman ", "Miles Stoudenmire "] -version = "0.9.10" +version = "0.9.11" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" From 2c5c3db65d2ed04189b5651a0749ce76cae9c38d Mon Sep 17 00:00:00 2001 From: Miles Date: Thu, 18 Sep 2025 13:52:25 -0400 Subject: [PATCH 5/6] Format test code --- test/base/test_decomp.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/base/test_decomp.jl b/test/base/test_decomp.jl index 88f78edc62..086715058d 100644 --- a/test/base/test_decomp.jl +++ b/test/base/test_decomp.jl @@ -510,7 +510,7 @@ end # HPSD Operator (Out,In) case # M = random_itensor(s, dag(t)) - O = prime(M,s)*dag(M) + O = prime(M, s)*dag(M) @test dir(inds(O)[1]) == ITensors.Out @test dir(inds(O)[2]) == ITensors.In @@ -518,7 +518,7 @@ end rinds = [dag(s)] D_O, U = eigen(O, linds, rinds; ishermitian=true) @test norm(prime(U)*D_O*dag(U)-O) < 1E-10 - @test all(>=(0.),diag(array(D_O))) + @test all(>=(0.0), diag(array(D_O))) println() @@ -527,18 +527,18 @@ end # # Make ρ out of two squared states # to populate both blocks: (0,0) and (1,1) - ψ0 = random_itensor(t,s) - ρ0 = prime(dag(ψ0),s)*ψ0 + ψ0 = random_itensor(t, s) + ρ0 = prime(dag(ψ0), s)*ψ0 - ψ2 = random_itensor(QN("Nf",2,-1),t,s) - ρ2 = prime(dag(ψ2),s)*ψ2 + ψ2 = random_itensor(QN("Nf", 2, -1), t, s) + ρ2 = prime(dag(ψ2), s)*ψ2 ρ = ρ0/2 + ρ2/2 @test dir(inds(ρ)[1]) == ITensors.In @test dir(inds(ρ)[2]) == ITensors.Out D_ρ, U = eigen(ρ, [dag(s)'], [s]; ishermitian=true) - @test all(>=(0.),diag(array(D_ρ))) + @test all(>=(0.0), diag(array(D_ρ))) @test norm(prime(U)*D_ρ*dag(U)-ρ) < 1E-10 ITensors.disable_auto_fermion() end From 8b37bae7de64c007d75c4943363730e4249bd29d Mon Sep 17 00:00:00 2001 From: Miles Date: Thu, 18 Sep 2025 23:15:49 -0400 Subject: [PATCH 6/6] Update test/base/test_decomp.jl Co-authored-by: Matt Fishman --- test/base/test_decomp.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/base/test_decomp.jl b/test/base/test_decomp.jl index 086715058d..4c1ef4fb2c 100644 --- a/test/base/test_decomp.jl +++ b/test/base/test_decomp.jl @@ -520,8 +520,6 @@ end @test norm(prime(U)*D_O*dag(U)-O) < 1E-10 @test all(>=(0.0), diag(array(D_O))) - println() - # # HPSD Dual operator (In,Out) case #