From 08720d719df671df1520ebf49a1dbc7256ecfc1c Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 25 Jun 2026 21:40:48 +0200 Subject: [PATCH 01/18] Add Enzyme rules for factorizations --- Project.toml | 3 + ext/TensorKitEnzymeExt/TensorKitEnzymeExt.jl | 1 + ext/TensorKitEnzymeExt/factorizations.jl | 69 ++++++++++++++++++++ ext/TensorKitEnzymeExt/utility.jl | 1 + src/factorizations/pullbacks.jl | 36 ++++++++++ test/enzyme-factorizations/eig.jl | 31 +++++++++ test/enzyme-factorizations/eigh.jl | 33 ++++++++++ test/enzyme-factorizations/lq.jl | 28 ++++++++ test/enzyme-factorizations/projections.jl | 18 +++++ test/enzyme-factorizations/qr.jl | 30 +++++++++ test/enzyme-factorizations/svd.jl | 39 +++++++++++ 11 files changed, 289 insertions(+) create mode 100644 ext/TensorKitEnzymeExt/factorizations.jl create mode 100644 test/enzyme-factorizations/eig.jl create mode 100644 test/enzyme-factorizations/eigh.jl create mode 100644 test/enzyme-factorizations/lq.jl create mode 100644 test/enzyme-factorizations/projections.jl create mode 100644 test/enzyme-factorizations/qr.jl create mode 100644 test/enzyme-factorizations/svd.jl diff --git a/Project.toml b/Project.toml index 5edabec65..62a954915 100644 --- a/Project.toml +++ b/Project.toml @@ -42,6 +42,9 @@ TensorKitFiniteDifferencesExt = "FiniteDifferences" TensorKitGPUArraysExt = "GPUArrays" TensorKitMooncakeExt = "Mooncake" +[sources] +MatrixAlgebraKit = {url = "https://github.com/quantumkithub/matrixalgebrakit.jl", rev = "main"} + [compat] AMDGPU = "2" Adapt = "4" diff --git a/ext/TensorKitEnzymeExt/TensorKitEnzymeExt.jl b/ext/TensorKitEnzymeExt/TensorKitEnzymeExt.jl index cadae496a..2095b3c52 100644 --- a/ext/TensorKitEnzymeExt/TensorKitEnzymeExt.jl +++ b/ext/TensorKitEnzymeExt/TensorKitEnzymeExt.jl @@ -15,5 +15,6 @@ include("utility.jl") include("linalg.jl") include("indexmanipulations.jl") include("tensoroperations.jl") +include("factorizations.jl") end diff --git a/ext/TensorKitEnzymeExt/factorizations.jl b/ext/TensorKitEnzymeExt/factorizations.jl new file mode 100644 index 000000000..4e6b6e962 --- /dev/null +++ b/ext/TensorKitEnzymeExt/factorizations.jl @@ -0,0 +1,69 @@ +# need these due to Enzyme choking on blocks + +for f in (:project_hermitian, :project_antihermitian) + f! = Symbol(f, :!) + @eval begin + function EnzymeRules.augmented_primal( + config::EnzymeRules.RevConfigWidth{1}, + func::Const{typeof($f!)}, + ::Type{RT}, + A::Annotation{<:AbstractTensorMap}, + arg::Annotation{<:AbstractTensorMap}, + alg::Const, + ) where {RT} + $f!(A.val, arg.val, alg.val) + primal = EnzymeRules.needs_primal(config) ? arg.val : nothing + shadow = EnzymeRules.needs_shadow(config) ? arg.dval : nothing + cache = nothing + return EnzymeRules.AugmentedReturn(primal, shadow, cache) + end + function EnzymeRules.reverse( + config::EnzymeRules.RevConfigWidth{1}, + func::Const{typeof($f!)}, + ::Type{RT}, + cache, + A::Annotation{<:AbstractTensorMap}, + arg::Annotation{<:AbstractTensorMap}, + alg::Const, + ) where {RT} + if !isa(A, Const) && !isa(arg, Const) + $f!(arg.dval, arg.dval, alg.val) + if A.dval !== arg.dval + A.dval .+= arg.dval + make_zero!(arg.dval) + end + end + return (nothing, nothing, nothing) + end + function EnzymeRules.augmented_primal( + config::EnzymeRules.RevConfigWidth{1}, + func::Const{typeof($f)}, + ::Type{RT}, + A::Annotation{<:AbstractTensorMap}, + alg::Const, + ) where {RT} + ret = $f(A.val, alg.val) + dret = make_zero(ret) + primal = EnzymeRules.needs_primal(config) ? ret : nothing + shadow = EnzymeRules.needs_shadow(config) ? dret : nothing + cache = dret + return EnzymeRules.AugmentedReturn(primal, shadow, cache) + end + function EnzymeRules.reverse( + config::EnzymeRules.RevConfigWidth{1}, + func::Const{typeof($f)}, + ::Type{RT}, + cache, + A::Annotation{<:AbstractTensorMap}, + alg::Const, + ) where {RT} + dret = cache + if !isa(A, Const) + $f!(dret, dret, alg.val) + add!(A.dval, dret) + end + make_zero!(dret) + return (nothing, nothing) + end + end +end diff --git a/ext/TensorKitEnzymeExt/utility.jl b/ext/TensorKitEnzymeExt/utility.jl index c0f178cf0..ff7659499 100644 --- a/ext/TensorKitEnzymeExt/utility.jl +++ b/ext/TensorKitEnzymeExt/utility.jl @@ -147,6 +147,7 @@ end @inline EnzymeRules.inactive(::typeof(TensorKit.insertleftunit), ::HomSpace, ::Any) = nothing @inline EnzymeRules.inactive(::typeof(TensorKit.insertrightunit), ::HomSpace, ::Any) = nothing @inline EnzymeRules.inactive(::typeof(TensorKit.removeunit), ::HomSpace, ::Any) = nothing +@inline EnzymeRules.inactive(::typeof(TensorKit.infimum), ::Any, ::Any) = nothing @inline EnzymeRules.inactive(::typeof(TensorKit.sectorstructure), ::Any) = nothing @inline EnzymeRules.inactive(::typeof(TensorKit.degeneracystructure), ::Any) = nothing @inline EnzymeRules.inactive(::typeof(TensorKit.select), s::HomSpace, i::Index2Tuple) = nothing diff --git a/src/factorizations/pullbacks.jl b/src/factorizations/pullbacks.jl index b910a184c..e0a044ebb 100644 --- a/src/factorizations/pullbacks.jl +++ b/src/factorizations/pullbacks.jl @@ -11,6 +11,16 @@ for pullback! in ( end return Δt end + @eval function MAK.$pullback!( + Δt::AbstractTensorMap, ::Nothing, F, ΔF; kwargs... + ) + foreachblock(Δt) do c, (Δb,) + Fc = block.(F, Ref(c)) + ΔFc = block.(ΔF, Ref(c)) + return MAK.$pullback!(Δb, nothing, Fc, ΔFc; kwargs...) + end + return Δt + end end for pullback! in (:qr_null_pullback!, :lq_null_pullback!) @eval function MAK.$pullback!( @@ -41,6 +51,28 @@ for pullback! in (:svd_pullback!, :eig_pullback!, :eigh_pullback!) end return Δt end + @eval function MAK.$pullback!( + Δt::AbstractTensorMap, ::Nothing, F, ΔF, inds; kwargs... + ) + foreachblock(Δt) do c, (Δb,) + haskey(inds, c) || return nothing + ind = inds[c] + Fc = block.(F, Ref(c)) + ΔFc = block.(ΔF, Ref(c)) + return MAK.$pullback!(Δb, nothing, Fc, ΔFc, ind; kwargs...) + end + return Δt + end + @eval function MAK.$pullback!( + Δt::AbstractTensorMap, t::AbstractTensorMap, F, ΔF, ::Colon; kwargs... + ) + return MAK.$pullback!(Δt, t, F, ΔF, _notrunc_ind(t); kwargs...) + end + @eval function MAK.$pullback!( + Δt, ::Nothing, F, ΔF; kwargs... + ) + return MAK.$pullback!(Δt, nothing, F, ΔF, _notrunc_ind(Δt); kwargs...) + end end for pullback_trunc! in (:svd_trunc_pullback!, :eig_trunc_pullback!, :eigh_trunc_pullback!) @@ -97,3 +129,7 @@ function MAK.remove_svd_gauge_dependence!( end return ΔU, ΔVᴴ end + +MAK.has_equal_storage(A::AbstractTensorMap, B::AbstractTensorMap) = A === B +MAK.has_equal_storage(A::AbstractTensorMap, B::SectorVector) = false +MAK.has_equal_storage(A::SectorVector, B::AbstractTensorMap) = false diff --git a/test/enzyme-factorizations/eig.jl b/test/enzyme-factorizations/eig.jl new file mode 100644 index 000000000..812017a64 --- /dev/null +++ b/test/enzyme-factorizations/eig.jl @@ -0,0 +1,31 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using VectorInterface: Zero, One +using MatrixAlgebraKit +using MatrixAlgebraKit: remove_eig_gauge_dependence! +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations (EIG): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) + atol = default_tol(T) + rtol = default_tol(T) + DV = eig_full(t) + ΔDV = EnzymeTestUtils.rand_tangent(DV) + remove_eig_gauge_dependence!(ΔDV[2], DV...) + EnzymeTestUtils.test_reverse(eig_full, Duplicated, (t, Duplicated); output_tangent = ΔDV, atol, rtol) + + #D = eig_vals(t) + #EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) + + V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(eig_trunc_no_error, t, nothing; trunc) + DVtrunc = eig_trunc_no_error(t, alg) + ΔDVtrunc = EnzymeTestUtils.rand_tangent(DVtrunc) + remove_eig_gauge_dependence!(ΔDVtrunc[2], DVtrunc...) + EnzymeTestUtils.test_reverse(eig_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) +end diff --git a/test/enzyme-factorizations/eigh.jl b/test/enzyme-factorizations/eigh.jl new file mode 100644 index 000000000..d465123cf --- /dev/null +++ b/test/enzyme-factorizations/eigh.jl @@ -0,0 +1,33 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using MatrixAlgebraKit +using MatrixAlgebraKit: remove_eigh_gauge_dependence! +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations (EIGH): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) + atol = default_tol(T) + rtol = default_tol(T) + th = project_hermitian(t) + DV = eigh_full(th) + ΔDV = EnzymeTestUtils.rand_tangent(DV) + remove_eigh_gauge_dependence!(ΔDV[2], DV...) + proj_eigh_full(t) = eigh_full(project_hermitian(t)) + EnzymeTestUtils.test_reverse(proj_eigh_full, Duplicated, (th, Duplicated); output_tangent = ΔDV, atol, rtol) + + #D = eigh_vals(th) + #EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) + + V_trunc = spacetype(th)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(eigh_trunc_no_error, th, nothing; trunc) + DVtrunc = eigh_trunc_no_error(th, alg) + ΔDVtrunc = EnzymeTestUtils.rand_tangent(DVtrunc) + remove_eigh_gauge_dependence!(ΔDVtrunc[2], DVtrunc...) + proj_eigh(t, alg) = eigh_trunc_no_error(project_hermitian(t), alg) + EnzymeTestUtils.test_reverse(proj_eigh, Duplicated, (th, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) +end diff --git a/test/enzyme-factorizations/lq.jl b/test/enzyme-factorizations/lq.jl new file mode 100644 index 000000000..d081a0ec9 --- /dev/null +++ b/test/enzyme-factorizations/lq.jl @@ -0,0 +1,28 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using MatrixAlgebraKit +using MatrixAlgebraKit: remove_lq_gauge_dependence!, remove_lq_null_gauge_dependence! +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations (LQ): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, A in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) + atol = default_tol(T) + rtol = default_tol(T) + EnzymeTestUtils.test_reverse(lq_compact, Duplicated, (A, Duplicated); atol, rtol) + + # lq_full/lq_null requires being careful with gauges + LQ = lq_full(A) + ΔLQ = EnzymeTestUtils.rand_tangent(LQ) + remove_lq_gauge_dependence!(ΔLQ..., A, LQ...) + EnzymeTestUtils.test_reverse(lq_full, Duplicated, (A, Duplicated); output_tangent = ΔLQ, atol, rtol) + + Nᴴ = lq_null(A) + Q = lq_compact(A)[2] + ΔNᴴ = EnzymeTestUtils.rand_tangent(Nᴴ) + remove_lq_null_gauge_dependence!(ΔNᴴ, Q, Nᴴ) + EnzymeTestUtils.test_reverse(lq_null, Duplicated, (A, Duplicated); output_tangent = ΔNᴴ, atol, rtol) +end diff --git a/test/enzyme-factorizations/projections.jl b/test/enzyme-factorizations/projections.jl new file mode 100644 index 000000000..1b5b3a28f --- /dev/null +++ b/test/enzyme-factorizations/projections.jl @@ -0,0 +1,18 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using MatrixAlgebraKit +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations (PROJECTIONS): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) + atol = default_tol(T) + rtol = default_tol(T) + EnzymeTestUtils.test_reverse(project_hermitian, Duplicated, (t, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(project_antihermitian, Duplicated, (t, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(project_hermitian!, Duplicated, (t, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(project_antihermitian!, Duplicated, (t, Duplicated); atol, rtol) +end diff --git a/test/enzyme-factorizations/qr.jl b/test/enzyme-factorizations/qr.jl new file mode 100644 index 000000000..d57a2baaa --- /dev/null +++ b/test/enzyme-factorizations/qr.jl @@ -0,0 +1,30 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using VectorInterface: Zero, One +using MatrixAlgebraKit +using MatrixAlgebraKit: remove_qr_gauge_dependence!, remove_qr_null_gauge_dependence! +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations (QR): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, A in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ⊗ V[3] ← (V[4] ⊗ V[5])')) + atol = default_tol(T) + rtol = default_tol(T) + + EnzymeTestUtils.test_reverse(qr_compact, Duplicated, (A, Duplicated); atol, rtol) + + # qr_full/qr_null requires being careful with gauges + QR = qr_full(A) + ΔQR = EnzymeTestUtils.rand_tangent(QR) + remove_qr_gauge_dependence!(ΔQR..., A, QR...) + EnzymeTestUtils.test_reverse(qr_full, Duplicated, (A, Duplicated); output_tangent = ΔQR, atol, rtol) + + N = qr_null(A) + Q = qr_compact(A)[1] + ΔN = EnzymeTestUtils.rand_tangent(N) + remove_qr_null_gauge_dependence!(ΔN, A, N) + EnzymeTestUtils.test_reverse(qr_null, Duplicated, (A, Duplicated); atol, rtol, output_tangent = ΔN) +end diff --git a/test/enzyme-factorizations/svd.jl b/test/enzyme-factorizations/svd.jl new file mode 100644 index 000000000..405ef21ca --- /dev/null +++ b/test/enzyme-factorizations/svd.jl @@ -0,0 +1,39 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using MatrixAlgebraKit +using MatrixAlgebraKit: remove_svd_gauge_dependence! +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations (SVD): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) + atol = default_tol(T) + rtol = default_tol(T) + + #S = svd_vals(t) + #EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) + + USVᴴ = svd_full(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_full, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + + # ntuple related bug in Enzyme internals + @static if VERSION >= v"1.11.0-rc" + USVᴴ = svd_compact(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + + V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(svd_trunc_no_error, t, nothing; trunc) + USVᴴtrunc = svd_trunc_no_error(t, alg) + ΔUSVᴴtrunc = EnzymeTestUtils.rand_tangent(USVᴴtrunc) + remove_svd_gauge_dependence!(ΔUSVᴴtrunc[1], ΔUSVᴴtrunc[3], USVᴴtrunc...) + EnzymeTestUtils.test_reverse(svd_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔUSVᴴtrunc, atol, rtol) + end +end From 08fa87244efa4d49d77d026bbdbf61cc687ce955 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 13 Jul 2026 11:09:43 +0200 Subject: [PATCH 02/18] Bump MAK compat --- Project.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Project.toml b/Project.toml index 62a954915..5edabec65 100644 --- a/Project.toml +++ b/Project.toml @@ -42,9 +42,6 @@ TensorKitFiniteDifferencesExt = "FiniteDifferences" TensorKitGPUArraysExt = "GPUArrays" TensorKitMooncakeExt = "Mooncake" -[sources] -MatrixAlgebraKit = {url = "https://github.com/quantumkithub/matrixalgebrakit.jl", rev = "main"} - [compat] AMDGPU = "2" Adapt = "4" From 85e6624e2585c9aedc17f777976fb7b3f76e7c5c Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 13 Jul 2026 13:26:34 +0200 Subject: [PATCH 03/18] Fix ambiguity --- src/factorizations/pullbacks.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/factorizations/pullbacks.jl b/src/factorizations/pullbacks.jl index e0a044ebb..17dffdccf 100644 --- a/src/factorizations/pullbacks.jl +++ b/src/factorizations/pullbacks.jl @@ -69,7 +69,7 @@ for pullback! in (:svd_pullback!, :eig_pullback!, :eigh_pullback!) return MAK.$pullback!(Δt, t, F, ΔF, _notrunc_ind(t); kwargs...) end @eval function MAK.$pullback!( - Δt, ::Nothing, F, ΔF; kwargs... + Δt::AbstractTensorMap, ::Nothing, F, ΔF; kwargs... ) return MAK.$pullback!(Δt, nothing, F, ΔF, _notrunc_ind(Δt); kwargs...) end From 785041200c1f97fe90b3249c4cc56dcf8d04aecd Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 14 Jul 2026 14:48:44 +0200 Subject: [PATCH 04/18] Use MAK branch --- Project.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Project.toml b/Project.toml index 5edabec65..e71b78b95 100644 --- a/Project.toml +++ b/Project.toml @@ -66,3 +66,6 @@ TensorOperations = "5.5.2, 5.6" TupleTools = "1.5" VectorInterface = "0.6" julia = "1.10" + +[sources] +MatrixAlgebraKit = {url = "https://github.com/QuantumKitHub/MatrixAlgebraKit.jl", rev = "ksh/enz_cache"} From d50848405b1ef24ff9d0fe978ddb4270a72e38db Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 15 Jul 2026 10:21:44 -0400 Subject: [PATCH 05/18] Remove sources --- Project.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Project.toml b/Project.toml index e71b78b95..5edabec65 100644 --- a/Project.toml +++ b/Project.toml @@ -66,6 +66,3 @@ TensorOperations = "5.5.2, 5.6" TupleTools = "1.5" VectorInterface = "0.6" julia = "1.10" - -[sources] -MatrixAlgebraKit = {url = "https://github.com/QuantumKitHub/MatrixAlgebraKit.jl", rev = "ksh/enz_cache"} From 93ed759fe343bbc36e60ed1bd6588543758dff26 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 25 Jun 2026 21:40:48 +0200 Subject: [PATCH 06/18] Add Enzyme rules for factorizations --- Project.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Project.toml b/Project.toml index 5edabec65..62a954915 100644 --- a/Project.toml +++ b/Project.toml @@ -42,6 +42,9 @@ TensorKitFiniteDifferencesExt = "FiniteDifferences" TensorKitGPUArraysExt = "GPUArrays" TensorKitMooncakeExt = "Mooncake" +[sources] +MatrixAlgebraKit = {url = "https://github.com/quantumkithub/matrixalgebrakit.jl", rev = "main"} + [compat] AMDGPU = "2" Adapt = "4" From 58116a20815e96572203db6aadbeacb7af5972aa Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 13 Jul 2026 11:09:43 +0200 Subject: [PATCH 07/18] Bump MAK compat --- Project.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Project.toml b/Project.toml index 62a954915..5edabec65 100644 --- a/Project.toml +++ b/Project.toml @@ -42,9 +42,6 @@ TensorKitFiniteDifferencesExt = "FiniteDifferences" TensorKitGPUArraysExt = "GPUArrays" TensorKitMooncakeExt = "Mooncake" -[sources] -MatrixAlgebraKit = {url = "https://github.com/quantumkithub/matrixalgebrakit.jl", rev = "main"} - [compat] AMDGPU = "2" Adapt = "4" From bce96efbcabfbdbb5f703995b5ce16631e5d34aa Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 16 Jul 2026 16:21:21 +0200 Subject: [PATCH 08/18] Get _vals working? --- src/factorizations/diagonal.jl | 1 + src/factorizations/pullbacks.jl | 7 ++++++- test/enzyme-factorizations/eig.jl | 4 ++-- test/enzyme-factorizations/eigh.jl | 4 ++-- test/enzyme-factorizations/svd.jl | 29 +++++++++++++---------------- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/factorizations/diagonal.jl b/src/factorizations/diagonal.jl index dae550ea1..49261f24e 100644 --- a/src/factorizations/diagonal.jl +++ b/src/factorizations/diagonal.jl @@ -3,6 +3,7 @@ _repack_diagonal(d::DiagonalTensorMap) = Diagonal(d.data) _repack_diagonal(d::SectorVector) = Diagonal(parent(d)) +MAK.diagonal(t::SectorVector) = DiagonalTensorMap(t) MAK.diagview(t::DiagonalTensorMap) = SectorVector(t.data, TensorKit.diagonalblockstructure(space(t))) for f in ( diff --git a/src/factorizations/pullbacks.jl b/src/factorizations/pullbacks.jl index 17dffdccf..72ad94008 100644 --- a/src/factorizations/pullbacks.jl +++ b/src/factorizations/pullbacks.jl @@ -58,7 +58,7 @@ for pullback! in (:svd_pullback!, :eig_pullback!, :eigh_pullback!) haskey(inds, c) || return nothing ind = inds[c] Fc = block.(F, Ref(c)) - ΔFc = block.(ΔF, Ref(c)) + ΔFc = map(ΔFc -> isnothing(ΔFc) ? nothing : block(ΔFc, c), ΔF) return MAK.$pullback!(Δb, nothing, Fc, ΔFc, ind; kwargs...) end return Δt @@ -73,6 +73,11 @@ for pullback! in (:svd_pullback!, :eig_pullback!, :eigh_pullback!) ) return MAK.$pullback!(Δt, nothing, F, ΔF, _notrunc_ind(Δt); kwargs...) end + @eval function MAK.$pullback!( + Δt::AbstractTensorMap, ::Nothing, F, ΔF, ::Colon; kwargs... + ) + return MAK.$pullback!(Δt, nothing, F, ΔF, _notrunc_ind(Δt); kwargs...) + end end for pullback_trunc! in (:svd_trunc_pullback!, :eig_trunc_pullback!, :eigh_trunc_pullback!) diff --git a/test/enzyme-factorizations/eig.jl b/test/enzyme-factorizations/eig.jl index 812017a64..20037aa4c 100644 --- a/test/enzyme-factorizations/eig.jl +++ b/test/enzyme-factorizations/eig.jl @@ -18,8 +18,8 @@ eltypes = (Float64, ComplexF64) remove_eig_gauge_dependence!(ΔDV[2], DV...) EnzymeTestUtils.test_reverse(eig_full, Duplicated, (t, Duplicated); output_tangent = ΔDV, atol, rtol) - #D = eig_vals(t) - #EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) + D = eig_vals(t) + EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) trunc = truncspace(V_trunc) diff --git a/test/enzyme-factorizations/eigh.jl b/test/enzyme-factorizations/eigh.jl index d465123cf..049f8bb24 100644 --- a/test/enzyme-factorizations/eigh.jl +++ b/test/enzyme-factorizations/eigh.jl @@ -19,8 +19,8 @@ eltypes = (Float64, ComplexF64) proj_eigh_full(t) = eigh_full(project_hermitian(t)) EnzymeTestUtils.test_reverse(proj_eigh_full, Duplicated, (th, Duplicated); output_tangent = ΔDV, atol, rtol) - #D = eigh_vals(th) - #EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) + D = eigh_vals(th) + EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) V_trunc = spacetype(th)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) trunc = truncspace(V_trunc) diff --git a/test/enzyme-factorizations/svd.jl b/test/enzyme-factorizations/svd.jl index 405ef21ca..628aaba43 100644 --- a/test/enzyme-factorizations/svd.jl +++ b/test/enzyme-factorizations/svd.jl @@ -13,27 +13,24 @@ eltypes = (Float64, ComplexF64) atol = default_tol(T) rtol = default_tol(T) - #S = svd_vals(t) - #EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) + S = svd_vals(t) + EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) USVᴴ = svd_full(t) ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) EnzymeTestUtils.test_reverse(svd_full, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) - # ntuple related bug in Enzyme internals - @static if VERSION >= v"1.11.0-rc" - USVᴴ = svd_compact(t) - ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) - remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) - EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + USVᴴ = svd_compact(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) - V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) - trunc = truncspace(V_trunc) - alg = MatrixAlgebraKit.select_algorithm(svd_trunc_no_error, t, nothing; trunc) - USVᴴtrunc = svd_trunc_no_error(t, alg) - ΔUSVᴴtrunc = EnzymeTestUtils.rand_tangent(USVᴴtrunc) - remove_svd_gauge_dependence!(ΔUSVᴴtrunc[1], ΔUSVᴴtrunc[3], USVᴴtrunc...) - EnzymeTestUtils.test_reverse(svd_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔUSVᴴtrunc, atol, rtol) - end + V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(svd_trunc_no_error, t, nothing; trunc) + USVᴴtrunc = svd_trunc_no_error(t, alg) + ΔUSVᴴtrunc = EnzymeTestUtils.rand_tangent(USVᴴtrunc) + remove_svd_gauge_dependence!(ΔUSVᴴtrunc[1], ΔUSVᴴtrunc[3], USVᴴtrunc...) + EnzymeTestUtils.test_reverse(svd_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔUSVᴴtrunc, atol, rtol) end From d181600db5c330aedc0ab041230bf0fc358b7477 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 17 Jul 2026 10:56:18 +0200 Subject: [PATCH 09/18] Try consolidating --- test/enzyme-factorizations/eig.jl | 31 ----- test/enzyme-factorizations/eigh.jl | 33 ----- test/enzyme-factorizations/factorizations.jl | 123 +++++++++++++++++++ test/enzyme-factorizations/lq.jl | 28 ----- test/enzyme-factorizations/projections.jl | 18 --- test/enzyme-factorizations/qr.jl | 30 ----- test/enzyme-factorizations/svd.jl | 36 ------ 7 files changed, 123 insertions(+), 176 deletions(-) delete mode 100644 test/enzyme-factorizations/eig.jl delete mode 100644 test/enzyme-factorizations/eigh.jl create mode 100644 test/enzyme-factorizations/factorizations.jl delete mode 100644 test/enzyme-factorizations/lq.jl delete mode 100644 test/enzyme-factorizations/projections.jl delete mode 100644 test/enzyme-factorizations/qr.jl delete mode 100644 test/enzyme-factorizations/svd.jl diff --git a/test/enzyme-factorizations/eig.jl b/test/enzyme-factorizations/eig.jl deleted file mode 100644 index 20037aa4c..000000000 --- a/test/enzyme-factorizations/eig.jl +++ /dev/null @@ -1,31 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using VectorInterface: Zero, One -using MatrixAlgebraKit -using MatrixAlgebraKit: remove_eig_gauge_dependence! -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@timedtestset "Enzyme - Factorizations (EIG): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) - atol = default_tol(T) - rtol = default_tol(T) - DV = eig_full(t) - ΔDV = EnzymeTestUtils.rand_tangent(DV) - remove_eig_gauge_dependence!(ΔDV[2], DV...) - EnzymeTestUtils.test_reverse(eig_full, Duplicated, (t, Duplicated); output_tangent = ΔDV, atol, rtol) - - D = eig_vals(t) - EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) - - V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) - trunc = truncspace(V_trunc) - alg = MatrixAlgebraKit.select_algorithm(eig_trunc_no_error, t, nothing; trunc) - DVtrunc = eig_trunc_no_error(t, alg) - ΔDVtrunc = EnzymeTestUtils.rand_tangent(DVtrunc) - remove_eig_gauge_dependence!(ΔDVtrunc[2], DVtrunc...) - EnzymeTestUtils.test_reverse(eig_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) -end diff --git a/test/enzyme-factorizations/eigh.jl b/test/enzyme-factorizations/eigh.jl deleted file mode 100644 index 049f8bb24..000000000 --- a/test/enzyme-factorizations/eigh.jl +++ /dev/null @@ -1,33 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using MatrixAlgebraKit -using MatrixAlgebraKit: remove_eigh_gauge_dependence! -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@timedtestset "Enzyme - Factorizations (EIGH): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) - atol = default_tol(T) - rtol = default_tol(T) - th = project_hermitian(t) - DV = eigh_full(th) - ΔDV = EnzymeTestUtils.rand_tangent(DV) - remove_eigh_gauge_dependence!(ΔDV[2], DV...) - proj_eigh_full(t) = eigh_full(project_hermitian(t)) - EnzymeTestUtils.test_reverse(proj_eigh_full, Duplicated, (th, Duplicated); output_tangent = ΔDV, atol, rtol) - - D = eigh_vals(th) - EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) - - V_trunc = spacetype(th)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) - trunc = truncspace(V_trunc) - alg = MatrixAlgebraKit.select_algorithm(eigh_trunc_no_error, th, nothing; trunc) - DVtrunc = eigh_trunc_no_error(th, alg) - ΔDVtrunc = EnzymeTestUtils.rand_tangent(DVtrunc) - remove_eigh_gauge_dependence!(ΔDVtrunc[2], DVtrunc...) - proj_eigh(t, alg) = eigh_trunc_no_error(project_hermitian(t), alg) - EnzymeTestUtils.test_reverse(proj_eigh, Duplicated, (th, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) -end diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl new file mode 100644 index 000000000..d8f23114c --- /dev/null +++ b/test/enzyme-factorizations/factorizations.jl @@ -0,0 +1,123 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using MatrixAlgebraKit +using MatrixAlgebraKit: remove_svd_gauge_dependence! +using MatrixAlgebraKit: remove_eig_gauge_dependence! +using MatrixAlgebraKit: remove_eigh_gauge_dependence! +using MatrixAlgebraKit: remove_lq_gauge_dependence!, remove_lq_null_gauge_dependence! +using MatrixAlgebraKit: remove_qr_gauge_dependence!, remove_qr_null_gauge_dependence! +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) + atol = default_tol(T) + rtol = default_tol(T) + + @testset "SVD" begin + S = svd_vals(t) + EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) + + USVᴴ = svd_full(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_full, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + + USVᴴ = svd_compact(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + + V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(svd_trunc_no_error, t, nothing; trunc) + USVᴴtrunc = svd_trunc_no_error(t, alg) + ΔUSVᴴtrunc = EnzymeTestUtils.rand_tangent(USVᴴtrunc) + remove_svd_gauge_dependence!(ΔUSVᴴtrunc[1], ΔUSVᴴtrunc[3], USVᴴtrunc...) + EnzymeTestUtils.test_reverse(svd_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔUSVᴴtrunc, atol, rtol) + end + + @testset "LQ" begin + EnzymeTestUtils.test_reverse(lq_compact, Duplicated, (A, Duplicated); atol, rtol) + + # lq_full/lq_null requires being careful with gauges + LQ = lq_full(A) + ΔLQ = EnzymeTestUtils.rand_tangent(LQ) + remove_lq_gauge_dependence!(ΔLQ..., A, LQ...) + EnzymeTestUtils.test_reverse(lq_full, Duplicated, (A, Duplicated); output_tangent = ΔLQ, atol, rtol) + + Nᴴ = lq_null(A) + Q = lq_compact(A)[2] + ΔNᴴ = EnzymeTestUtils.rand_tangent(Nᴴ) + remove_lq_null_gauge_dependence!(ΔNᴴ, Q, Nᴴ) + EnzymeTestUtils.test_reverse(lq_null, Duplicated, (A, Duplicated); output_tangent = ΔNᴴ, atol, rtol) + end + + @testset "QR" begin + # qr_full/qr_null requires being careful with gauges + QR = qr_full(A) + ΔQR = EnzymeTestUtils.rand_tangent(QR) + remove_qr_gauge_dependence!(ΔQR..., A, QR...) + EnzymeTestUtils.test_reverse(qr_full, Duplicated, (A, Duplicated); output_tangent = ΔQR, atol, rtol) + + N = qr_null(A) + Q = qr_compact(A)[1] + ΔN = EnzymeTestUtils.rand_tangent(N) + remove_qr_null_gauge_dependence!(ΔN, A, N) + EnzymeTestUtils.test_reverse(qr_null, Duplicated, (A, Duplicated); atol, rtol, output_tangent = ΔN) + end +end + +@timedtestset "Enzyme - Factorizations (EIGH/EIG): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) + atol = default_tol(T) + rtol = default_tol(T) + + @testest "EIG" begin + DV = eig_full(t) + ΔDV = EnzymeTestUtils.rand_tangent(DV) + remove_eig_gauge_dependence!(ΔDV[2], DV...) + EnzymeTestUtils.test_reverse(eig_full, Duplicated, (t, Duplicated); output_tangent = ΔDV, atol, rtol) + + D = eig_vals(t) + EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) + + V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(eig_trunc_no_error, t, nothing; trunc) + DVtrunc = eig_trunc_no_error(t, alg) + ΔDVtrunc = EnzymeTestUtils.rand_tangent(DVtrunc) + remove_eig_gauge_dependence!(ΔDVtrunc[2], DVtrunc...) + EnzymeTestUtils.test_reverse(eig_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) + end + + @testest "EIGH" begin + th = project_hermitian(t) + DV = eigh_full(th) + ΔDV = EnzymeTestUtils.rand_tangent(DV) + remove_eigh_gauge_dependence!(ΔDV[2], DV...) + proj_eigh_full(t) = eigh_full(project_hermitian(t)) + EnzymeTestUtils.test_reverse(proj_eigh_full, Duplicated, (th, Duplicated); output_tangent = ΔDV, atol, rtol) + + D = eigh_vals(th) + EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) + + V_trunc = spacetype(th)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) + trunc = truncspace(V_trunc) + alg = MatrixAlgebraKit.select_algorithm(eigh_trunc_no_error, th, nothing; trunc) + DVtrunc = eigh_trunc_no_error(th, alg) + ΔDVtrunc = EnzymeTestUtils.rand_tangent(DVtrunc) + remove_eigh_gauge_dependence!(ΔDVtrunc[2], DVtrunc...) + proj_eigh(t, alg) = eigh_trunc_no_error(project_hermitian(t), alg) + EnzymeTestUtils.test_reverse(proj_eigh, Duplicated, (th, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) + end + + @testset "Projections" begin + EnzymeTestUtils.test_reverse(project_hermitian, Duplicated, (t, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(project_antihermitian, Duplicated, (t, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(project_hermitian!, Duplicated, (t, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(project_antihermitian!, Duplicated, (t, Duplicated); atol, rtol) + end +end diff --git a/test/enzyme-factorizations/lq.jl b/test/enzyme-factorizations/lq.jl deleted file mode 100644 index d081a0ec9..000000000 --- a/test/enzyme-factorizations/lq.jl +++ /dev/null @@ -1,28 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using MatrixAlgebraKit -using MatrixAlgebraKit: remove_lq_gauge_dependence!, remove_lq_null_gauge_dependence! -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@timedtestset "Enzyme - Factorizations (LQ): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, A in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) - atol = default_tol(T) - rtol = default_tol(T) - EnzymeTestUtils.test_reverse(lq_compact, Duplicated, (A, Duplicated); atol, rtol) - - # lq_full/lq_null requires being careful with gauges - LQ = lq_full(A) - ΔLQ = EnzymeTestUtils.rand_tangent(LQ) - remove_lq_gauge_dependence!(ΔLQ..., A, LQ...) - EnzymeTestUtils.test_reverse(lq_full, Duplicated, (A, Duplicated); output_tangent = ΔLQ, atol, rtol) - - Nᴴ = lq_null(A) - Q = lq_compact(A)[2] - ΔNᴴ = EnzymeTestUtils.rand_tangent(Nᴴ) - remove_lq_null_gauge_dependence!(ΔNᴴ, Q, Nᴴ) - EnzymeTestUtils.test_reverse(lq_null, Duplicated, (A, Duplicated); output_tangent = ΔNᴴ, atol, rtol) -end diff --git a/test/enzyme-factorizations/projections.jl b/test/enzyme-factorizations/projections.jl deleted file mode 100644 index 1b5b3a28f..000000000 --- a/test/enzyme-factorizations/projections.jl +++ /dev/null @@ -1,18 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using MatrixAlgebraKit -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@timedtestset "Enzyme - Factorizations (PROJECTIONS): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) - atol = default_tol(T) - rtol = default_tol(T) - EnzymeTestUtils.test_reverse(project_hermitian, Duplicated, (t, Duplicated); atol, rtol) - EnzymeTestUtils.test_reverse(project_antihermitian, Duplicated, (t, Duplicated); atol, rtol) - EnzymeTestUtils.test_reverse(project_hermitian!, Duplicated, (t, Duplicated); atol, rtol) - EnzymeTestUtils.test_reverse(project_antihermitian!, Duplicated, (t, Duplicated); atol, rtol) -end diff --git a/test/enzyme-factorizations/qr.jl b/test/enzyme-factorizations/qr.jl deleted file mode 100644 index d57a2baaa..000000000 --- a/test/enzyme-factorizations/qr.jl +++ /dev/null @@ -1,30 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using VectorInterface: Zero, One -using MatrixAlgebraKit -using MatrixAlgebraKit: remove_qr_gauge_dependence!, remove_qr_null_gauge_dependence! -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@timedtestset "Enzyme - Factorizations (QR): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, A in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ⊗ V[3] ← (V[4] ⊗ V[5])')) - atol = default_tol(T) - rtol = default_tol(T) - - EnzymeTestUtils.test_reverse(qr_compact, Duplicated, (A, Duplicated); atol, rtol) - - # qr_full/qr_null requires being careful with gauges - QR = qr_full(A) - ΔQR = EnzymeTestUtils.rand_tangent(QR) - remove_qr_gauge_dependence!(ΔQR..., A, QR...) - EnzymeTestUtils.test_reverse(qr_full, Duplicated, (A, Duplicated); output_tangent = ΔQR, atol, rtol) - - N = qr_null(A) - Q = qr_compact(A)[1] - ΔN = EnzymeTestUtils.rand_tangent(N) - remove_qr_null_gauge_dependence!(ΔN, A, N) - EnzymeTestUtils.test_reverse(qr_null, Duplicated, (A, Duplicated); atol, rtol, output_tangent = ΔN) -end diff --git a/test/enzyme-factorizations/svd.jl b/test/enzyme-factorizations/svd.jl deleted file mode 100644 index 628aaba43..000000000 --- a/test/enzyme-factorizations/svd.jl +++ /dev/null @@ -1,36 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using MatrixAlgebraKit -using MatrixAlgebraKit: remove_svd_gauge_dependence! -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@timedtestset "Enzyme - Factorizations (SVD): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) - atol = default_tol(T) - rtol = default_tol(T) - - S = svd_vals(t) - EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) - - USVᴴ = svd_full(t) - ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) - remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) - EnzymeTestUtils.test_reverse(svd_full, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) - - USVᴴ = svd_compact(t) - ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) - remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) - EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) - - V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) - trunc = truncspace(V_trunc) - alg = MatrixAlgebraKit.select_algorithm(svd_trunc_no_error, t, nothing; trunc) - USVᴴtrunc = svd_trunc_no_error(t, alg) - ΔUSVᴴtrunc = EnzymeTestUtils.rand_tangent(USVᴴtrunc) - remove_svd_gauge_dependence!(ΔUSVᴴtrunc[1], ΔUSVᴴtrunc[3], USVᴴtrunc...) - EnzymeTestUtils.test_reverse(svd_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔUSVᴴtrunc, atol, rtol) -end From 943ab91f56d536a2da46eb9206c97104394ea2ff Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 17 Jul 2026 11:48:38 +0200 Subject: [PATCH 10/18] Fix variable naming --- test/enzyme-factorizations/factorizations.jl | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index d8f23114c..d36b0c35f 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -41,33 +41,33 @@ eltypes = (Float64, ComplexF64) end @testset "LQ" begin - EnzymeTestUtils.test_reverse(lq_compact, Duplicated, (A, Duplicated); atol, rtol) + EnzymeTestUtils.test_reverse(lq_compact, Duplicated, (t, Duplicated); atol, rtol) # lq_full/lq_null requires being careful with gauges - LQ = lq_full(A) + LQ = lq_full(t) ΔLQ = EnzymeTestUtils.rand_tangent(LQ) - remove_lq_gauge_dependence!(ΔLQ..., A, LQ...) - EnzymeTestUtils.test_reverse(lq_full, Duplicated, (A, Duplicated); output_tangent = ΔLQ, atol, rtol) + remove_lq_gauge_dependence!(ΔLQ..., t, LQ...) + EnzymeTestUtils.test_reverse(lq_full, Duplicated, (t, Duplicated); output_tangent = ΔLQ, atol, rtol) - Nᴴ = lq_null(A) - Q = lq_compact(A)[2] + Nᴴ = lq_null(t) + Q = lq_compact(t)[2] ΔNᴴ = EnzymeTestUtils.rand_tangent(Nᴴ) remove_lq_null_gauge_dependence!(ΔNᴴ, Q, Nᴴ) - EnzymeTestUtils.test_reverse(lq_null, Duplicated, (A, Duplicated); output_tangent = ΔNᴴ, atol, rtol) + EnzymeTestUtils.test_reverse(lq_null, Duplicated, (t, Duplicated); output_tangent = ΔNᴴ, atol, rtol) end @testset "QR" begin # qr_full/qr_null requires being careful with gauges - QR = qr_full(A) + QR = qr_full(t) ΔQR = EnzymeTestUtils.rand_tangent(QR) - remove_qr_gauge_dependence!(ΔQR..., A, QR...) - EnzymeTestUtils.test_reverse(qr_full, Duplicated, (A, Duplicated); output_tangent = ΔQR, atol, rtol) + remove_qr_gauge_dependence!(ΔQR..., t, QR...) + EnzymeTestUtils.test_reverse(qr_full, Duplicated, (t, Duplicated); output_tangent = ΔQR, atol, rtol) - N = qr_null(A) - Q = qr_compact(A)[1] + N = qr_null(t) + Q = qr_compact(t)[1] ΔN = EnzymeTestUtils.rand_tangent(N) - remove_qr_null_gauge_dependence!(ΔN, A, N) - EnzymeTestUtils.test_reverse(qr_null, Duplicated, (A, Duplicated); atol, rtol, output_tangent = ΔN) + remove_qr_null_gauge_dependence!(ΔN, t, N) + EnzymeTestUtils.test_reverse(qr_null, Duplicated, (t, Duplicated); atol, rtol, output_tangent = ΔN) end end From 2bbf2d5cd71313d63addbb18309793b12709c36a Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 17 Jul 2026 14:31:21 +0200 Subject: [PATCH 11/18] more typos --- test/enzyme-factorizations/factorizations.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index d36b0c35f..d2f4e66ef 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -75,7 +75,7 @@ end atol = default_tol(T) rtol = default_tol(T) - @testest "EIG" begin + @testset "EIG" begin DV = eig_full(t) ΔDV = EnzymeTestUtils.rand_tangent(DV) remove_eig_gauge_dependence!(ΔDV[2], DV...) @@ -93,7 +93,7 @@ end EnzymeTestUtils.test_reverse(eig_trunc_no_error, Duplicated, (t, Duplicated), (alg, Const); output_tangent = ΔDVtrunc, atol, rtol) end - @testest "EIGH" begin + @testset "EIGH" begin th = project_hermitian(t) DV = eigh_full(th) ΔDV = EnzymeTestUtils.rand_tangent(DV) From ecd5ef3cdc20d2d4a4f11252bdf0171b172f0a64 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 20 Jul 2026 09:21:09 +0200 Subject: [PATCH 12/18] Try cutting down what runs on CI --- Project.toml | 2 +- test/enzyme-factorizations/factorizations.jl | 105 +++++++++++-------- 2 files changed, 60 insertions(+), 47 deletions(-) diff --git a/Project.toml b/Project.toml index 5edabec65..ae78dc070 100644 --- a/Project.toml +++ b/Project.toml @@ -60,7 +60,7 @@ OhMyThreads = "0.8.0" Printf = "1" Random = "1" ScopedValues = "1.3.0" -Strided = "2.6.1" +Strided = "2.6.3" TensorKitSectors = "0.3.7" TensorOperations = "5.5.2, 5.6" TupleTools = "1.5" diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index d2f4e66ef..f022fa66c 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -12,24 +12,27 @@ using Random spacelist = ad_spacelist(fast_tests) eltypes = (Float64, ComplexF64) +is_ci = get(ENV, "CI", "false") == "true" @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) atol = default_tol(T) rtol = default_tol(T) @testset "SVD" begin - S = svd_vals(t) - EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) + if !is_ci + S = svd_vals(t) + EnzymeTestUtils.test_reverse(svd_vals, Duplicated, (t, Duplicated); atol, rtol) - USVᴴ = svd_full(t) - ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) - remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) - EnzymeTestUtils.test_reverse(svd_full, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + USVᴴ = svd_full(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_full, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) - USVᴴ = svd_compact(t) - ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) - remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) - EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + USVᴴ = svd_compact(t) + ΔUSVᴴ = EnzymeTestUtils.rand_tangent(USVᴴ) + remove_svd_gauge_dependence!(ΔUSVᴴ[1], ΔUSVᴴ[3], USVᴴ...) + EnzymeTestUtils.test_reverse(svd_compact, Duplicated, (t, Duplicated); output_tangent = ΔUSVᴴ, atol, rtol) + end V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) trunc = truncspace(V_trunc) @@ -43,31 +46,37 @@ eltypes = (Float64, ComplexF64) @testset "LQ" begin EnzymeTestUtils.test_reverse(lq_compact, Duplicated, (t, Duplicated); atol, rtol) - # lq_full/lq_null requires being careful with gauges - LQ = lq_full(t) - ΔLQ = EnzymeTestUtils.rand_tangent(LQ) - remove_lq_gauge_dependence!(ΔLQ..., t, LQ...) - EnzymeTestUtils.test_reverse(lq_full, Duplicated, (t, Duplicated); output_tangent = ΔLQ, atol, rtol) - - Nᴴ = lq_null(t) - Q = lq_compact(t)[2] - ΔNᴴ = EnzymeTestUtils.rand_tangent(Nᴴ) - remove_lq_null_gauge_dependence!(ΔNᴴ, Q, Nᴴ) - EnzymeTestUtils.test_reverse(lq_null, Duplicated, (t, Duplicated); output_tangent = ΔNᴴ, atol, rtol) + if !is_ci + # lq_full/lq_null requires being careful with gauges + LQ = lq_full(t) + ΔLQ = EnzymeTestUtils.rand_tangent(LQ) + remove_lq_gauge_dependence!(ΔLQ..., t, LQ...) + EnzymeTestUtils.test_reverse(lq_full, Duplicated, (t, Duplicated); output_tangent = ΔLQ, atol, rtol) + + Nᴴ = lq_null(t) + Q = lq_compact(t)[2] + ΔNᴴ = EnzymeTestUtils.rand_tangent(Nᴴ) + remove_lq_null_gauge_dependence!(ΔNᴴ, Q, Nᴴ) + EnzymeTestUtils.test_reverse(lq_null, Duplicated, (t, Duplicated); output_tangent = ΔNᴴ, atol, rtol) + end end @testset "QR" begin - # qr_full/qr_null requires being careful with gauges - QR = qr_full(t) - ΔQR = EnzymeTestUtils.rand_tangent(QR) - remove_qr_gauge_dependence!(ΔQR..., t, QR...) - EnzymeTestUtils.test_reverse(qr_full, Duplicated, (t, Duplicated); output_tangent = ΔQR, atol, rtol) - - N = qr_null(t) - Q = qr_compact(t)[1] - ΔN = EnzymeTestUtils.rand_tangent(N) - remove_qr_null_gauge_dependence!(ΔN, t, N) - EnzymeTestUtils.test_reverse(qr_null, Duplicated, (t, Duplicated); atol, rtol, output_tangent = ΔN) + EnzymeTestUtils.test_reverse(qr_compact, Duplicated, (t, Duplicated); atol, rtol) + + if !is_ci + # qr_full/qr_null requires being careful with gauges + QR = qr_full(t) + ΔQR = EnzymeTestUtils.rand_tangent(QR) + remove_qr_gauge_dependence!(ΔQR..., t, QR...) + EnzymeTestUtils.test_reverse(qr_full, Duplicated, (t, Duplicated); output_tangent = ΔQR, atol, rtol) + + N = qr_null(t) + Q = qr_compact(t)[1] + ΔN = EnzymeTestUtils.rand_tangent(N) + remove_qr_null_gauge_dependence!(ΔN, t, N) + EnzymeTestUtils.test_reverse(qr_null, Duplicated, (t, Duplicated); atol, rtol, output_tangent = ΔN) + end end end @@ -76,13 +85,15 @@ end rtol = default_tol(T) @testset "EIG" begin - DV = eig_full(t) - ΔDV = EnzymeTestUtils.rand_tangent(DV) - remove_eig_gauge_dependence!(ΔDV[2], DV...) - EnzymeTestUtils.test_reverse(eig_full, Duplicated, (t, Duplicated); output_tangent = ΔDV, atol, rtol) + if !is_ci + DV = eig_full(t) + ΔDV = EnzymeTestUtils.rand_tangent(DV) + remove_eig_gauge_dependence!(ΔDV[2], DV...) + EnzymeTestUtils.test_reverse(eig_full, Duplicated, (t, Duplicated); output_tangent = ΔDV, atol, rtol) - D = eig_vals(t) - EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) + D = eig_vals(t) + EnzymeTestUtils.test_reverse(eig_vals, Duplicated, (t, Duplicated); atol, rtol) + end V_trunc = spacetype(t)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) trunc = truncspace(V_trunc) @@ -95,14 +106,16 @@ end @testset "EIGH" begin th = project_hermitian(t) - DV = eigh_full(th) - ΔDV = EnzymeTestUtils.rand_tangent(DV) - remove_eigh_gauge_dependence!(ΔDV[2], DV...) - proj_eigh_full(t) = eigh_full(project_hermitian(t)) - EnzymeTestUtils.test_reverse(proj_eigh_full, Duplicated, (th, Duplicated); output_tangent = ΔDV, atol, rtol) - - D = eigh_vals(th) - EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) + if !is_ci + DV = eigh_full(th) + ΔDV = EnzymeTestUtils.rand_tangent(DV) + remove_eigh_gauge_dependence!(ΔDV[2], DV...) + proj_eigh_full(t) = eigh_full(project_hermitian(t)) + EnzymeTestUtils.test_reverse(proj_eigh_full, Duplicated, (th, Duplicated); output_tangent = ΔDV, atol, rtol) + + D = eigh_vals(th) + EnzymeTestUtils.test_reverse(eigh_vals ∘ project_hermitian, Duplicated, (th, Duplicated); atol, rtol) + end V_trunc = spacetype(th)(c => min(size(b)...) ÷ 2 for (c, b) in blocks(t)) trunc = truncspace(V_trunc) From 4a3aecc7882c4176bafa514ab9b2ef8bb2ad7464 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 20 Jul 2026 10:55:32 +0200 Subject: [PATCH 13/18] Try to find problematic Enzyme version and minimal passing fact tests --- test/enzyme-factorizations/factorizations.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index f022fa66c..a9fba1ef4 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -10,10 +10,11 @@ using MatrixAlgebraKit: remove_qr_gauge_dependence!, remove_qr_null_gauge_depend using Enzyme, EnzymeTestUtils using Random -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) is_ci = get(ENV, "CI", "false") == "true" +spacelist = is_ci ? [ad_spacelist(fast_tests)[1]] : ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) atol = default_tol(T) rtol = default_tol(T) From b1ae9247f4f81b702b2b2b438ceedafd1b30e9a7 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 20 Jul 2026 18:15:15 +0200 Subject: [PATCH 14/18] Try a few more --- test/enzyme-factorizations/factorizations.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index a9fba1ef4..4b602dfbb 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -12,7 +12,7 @@ using Random is_ci = get(ENV, "CI", "false") == "true" -spacelist = is_ci ? [ad_spacelist(fast_tests)[1]] : ad_spacelist(fast_tests) +spacelist = is_ci ? ad_spacelist(fast_tests)[1:2] : ad_spacelist(fast_tests) eltypes = (Float64, ComplexF64) @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) From c7d4de8d00d6e0114477c061cbfc7223915bd8ad Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 20 Jul 2026 19:47:51 +0200 Subject: [PATCH 15/18] Expand even more --- test/enzyme-factorizations/factorizations.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index 4b602dfbb..9cc162ee0 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -12,7 +12,7 @@ using Random is_ci = get(ENV, "CI", "false") == "true" -spacelist = is_ci ? ad_spacelist(fast_tests)[1:2] : ad_spacelist(fast_tests) +spacelist = is_ci ? ad_spacelist(fast_tests)[1:3] : ad_spacelist(fast_tests) eltypes = (Float64, ComplexF64) @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) From 1cb9ce60e170fe3fc8ca39bb9459b78a8fb04f69 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 23 Jul 2026 14:36:37 +0200 Subject: [PATCH 16/18] Go back to full ad_spacelist --- test/enzyme-factorizations/factorizations.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index 9cc162ee0..97ba2779b 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -12,7 +12,7 @@ using Random is_ci = get(ENV, "CI", "false") == "true" -spacelist = is_ci ? ad_spacelist(fast_tests)[1:3] : ad_spacelist(fast_tests) +spacelist = ad_spacelist(fast_tests) eltypes = (Float64, ComplexF64) @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) From 521a0163822f2e07c1c852d40fd36abaf254f812 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 24 Jul 2026 10:07:48 +0200 Subject: [PATCH 17/18] Try just the hardest case --- test/enzyme-factorizations/factorizations.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index 97ba2779b..97925719e 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -12,7 +12,7 @@ using Random is_ci = get(ENV, "CI", "false") == "true" -spacelist = ad_spacelist(fast_tests) +spacelist = [ad_spacelist(fast_tests)[end]] eltypes = (Float64, ComplexF64) @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) From 215e3f05f09a1653f6ebe7992e8803348ba2ab12 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 24 Jul 2026 18:03:54 +0200 Subject: [PATCH 18/18] Force GC, empty caches, and extend timeout a bit --- .github/workflows/CI.yml | 2 +- test/enzyme-factorizations/factorizations.jl | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3e620460d..8dad11b0a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,6 +22,6 @@ jobs: with: fast: "${{ github.event.pull_request.draft == true }}" exclude: '["cuda", "amd"]' - timeout-minutes: 120 + timeout-minutes: 150 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/test/enzyme-factorizations/factorizations.jl b/test/enzyme-factorizations/factorizations.jl index 97925719e..c390d073f 100644 --- a/test/enzyme-factorizations/factorizations.jl +++ b/test/enzyme-factorizations/factorizations.jl @@ -12,7 +12,7 @@ using Random is_ci = get(ENV, "CI", "false") == "true" -spacelist = [ad_spacelist(fast_tests)[end]] +spacelist = ad_spacelist(fast_tests) eltypes = (Float64, ComplexF64) @timedtestset "Enzyme - Factorizations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]), randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])')) @@ -79,6 +79,8 @@ eltypes = (Float64, ComplexF64) EnzymeTestUtils.test_reverse(qr_null, Duplicated, (t, Duplicated); atol, rtol, output_tangent = ΔN) end end + TensorKit.empty_globalcaches!() + GC.gc(true) end @timedtestset "Enzyme - Factorizations (EIGH/EIG): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, t in (randn(T, V[1] ← V[1]), rand(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2])) @@ -134,4 +136,6 @@ end EnzymeTestUtils.test_reverse(project_hermitian!, Duplicated, (t, Duplicated); atol, rtol) EnzymeTestUtils.test_reverse(project_antihermitian!, Duplicated, (t, Duplicated); atol, rtol) end + TensorKit.empty_globalcaches!() + GC.gc(true) end