diff --git a/Project.toml b/Project.toml index 10d69842f..bb1eccd27 100644 --- a/Project.toml +++ b/Project.toml @@ -48,7 +48,7 @@ Adapt = "4" CUDA = "6" ChainRulesCore = "1" Dictionaries = "0.4" -Enzyme = "0.13.157" +Enzyme = "0.13.183" EnzymeTestUtils = "0.2.8" FiniteDifferences = "0.12" GPUArrays = "11.4.1" diff --git a/test/enzyme-indexmanipulations-flip-twist/flip.jl b/test/enzyme-indexmanipulations-flip-twist/flip.jl deleted file mode 100644 index d410673e4..000000000 --- a/test/enzyme-indexmanipulations-flip-twist/flip.jl +++ /dev/null @@ -1,24 +0,0 @@ -using Test, TestExtras -using TensorKit -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -if !Sys.iswindows() && VERSION > v"1.11.0-rc" - @timedtestset "Enzyme - Index Manipulations (flip):" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T) TA ($TA)" for V in spacelist, T in eltypes, TA in (Duplicated,) - atol = default_tol(T) - rtol = default_tol(T) - has_braiding = BraidingStyle(sectortype(eltype(V))) isa HasBraiding - if has_braiding - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - EnzymeTestUtils.test_reverse(flip, TA, (A, TA), (1, Const); atol, rtol, fkwargs = (inv = false,)) - EnzymeTestUtils.test_reverse(flip, TA, (A, TA), [1, 3]; atol, rtol, fkwargs = (inv = true,)) - EnzymeTestUtils.test_reverse(flip, TA, (A, TA), (1, Const); atol, rtol) - EnzymeTestUtils.test_reverse(flip, TA, (A, TA), ([1, 3], Const); atol, rtol) - end - end - end -end diff --git a/test/enzyme-indexmanipulations-flip-twist/twist.jl b/test/enzyme-indexmanipulations-flip-twist/twist.jl deleted file mode 100644 index 6dedcdd5a..000000000 --- a/test/enzyme-indexmanipulations-flip-twist/twist.jl +++ /dev/null @@ -1,26 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using VectorInterface: Zero, One -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -if !Sys.iswindows() && VERSION > v"1.11.0-rc" - @timedtestset "Enzyme - Index Manipulations (twist):" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, TA in (Duplicated,) - atol = default_tol(T) - rtol = default_tol(T) - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - has_braiding = BraidingStyle(sectortype(eltype(V))) isa HasBraiding - if has_braiding && !(T <: Real && !(sectorscalartype(sectortype(A)) <: Real)) - EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), (1, Const); atol, rtol, fkwargs = (inv = false,)) - EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), ([1, 3], Const); atol, rtol, fkwargs = (inv = true,)) - EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), (1, Const); atol, rtol) - EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), ([1, 3], Const); atol, rtol) - end - end - end -end diff --git a/test/enzyme-indexmanipulations-transform/braid.jl b/test/enzyme-indexmanipulations-transform/braid.jl deleted file mode 100644 index 0d4099d13..000000000 --- a/test/enzyme-indexmanipulations-transform/braid.jl +++ /dev/null @@ -1,35 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" -Tαs = is_ci ? (Active,) : (Active, Const) -Tβs = is_ci ? (Active,) : (Active, Const) - -if !Sys.iswindows() && VERSION > v"1.11.0-rc" - @timedtestset "Enzyme - Index Manipulations (braid!) $(TensorKit.type_repr(sectortype(eltype(V)))) ($T) Tα $Tα Tβ $Tβ" for V in spacelist, T in eltypes, Tα in Tαs, Tβ in Tβs - atol = default_tol(T) - rtol = default_tol(T) - Vstr = TensorKit.type_repr(sectortype(eltype(V))) - has_braiding = BraidingStyle(sectortype(eltype(V))) isa HasBraiding - if has_braiding - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - α = randn(T) - β = randn(T) - p = randcircshift(numout(A), numin(A)) - levels = Tuple(randperm(numind(A))) - C = randn!(transpose(A, p)) - EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (levels, Const), (α, Tα), (β, Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") - if !(T <: Real) && !is_ci - EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (real(A), Duplicated), (p, Const), (levels, Const), (α, Tα), (β, Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") - EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (levels, Const), (real(α), Tα), (β, Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") - EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (levels, Const), (real(α), Tα), (real(β), Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") - end - end - end -end diff --git a/test/enzyme-indexmanipulations-transform/permute.jl b/test/enzyme-indexmanipulations-transform/permute.jl deleted file mode 100644 index d78ec1e41..000000000 --- a/test/enzyme-indexmanipulations-transform/permute.jl +++ /dev/null @@ -1,30 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" -Tαs = is_ci ? (Active,) : (Active, Const) -Tβs = is_ci ? (Active,) : (Active, Const) - -if VERSION >= v"1.11.0-rc" # segfault issues on 1.10 - @timedtestset "Enzyme - Index Manipulations (permute!): $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - println(TensorKit.type_repr(sectortype(eltype(V)))) - atol = default_tol(T) - rtol = default_tol(T) - symmetricbraiding = BraidingStyle(sectortype(eltype(V))) isa SymmetricBraiding - - symmetricbraiding && @timedtestset "permute! Tα $Tα, Tβ $Tβ" for Tα in Tαs, Tβ in Tβs - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - α = randn(T) - β = randn(T) - p = randindextuple(numind(A)) - C = randn!(permute(A, p)) - EnzymeTestUtils.test_reverse(TensorKit.permute!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (α, Tα), (β, Tβ); atol, rtol) - end - end -end diff --git a/test/enzyme-indexmanipulations-transform/transpose.jl b/test/enzyme-indexmanipulations-transform/transpose.jl deleted file mode 100644 index 7ba3e2d42..000000000 --- a/test/enzyme-indexmanipulations-transform/transpose.jl +++ /dev/null @@ -1,37 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using VectorInterface: Zero, One -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" - -Tαs = is_ci ? (Active,) : (Active, Const) -Tβs = is_ci ? (Active,) : (Active, Const) - -if VERSION > v"1.11.0-rc" # https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @timedtestset "Enzyme - Index Manipulations (transpose!) $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - α = randn(T) - β = randn(T) - - # repeat a couple times to get some distribution of arrows - p = randcircshift(numout(A), numin(A)) - C = randn!(transpose(A, p)) - !is_ci && EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (A, Duplicated), (p, Const), (One(), Const), (Zero(), Const); atol, rtol) - @testset for Tα in Tαs, Tβ in Tβs - EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (A, Duplicated), (p, Const), (α, Tα), (β, Tβ); atol, rtol) - if !(T <: Real) && !is_ci - EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (real(A), Duplicated), (p, Const), (α, Tα), (β, Tβ); atol, rtol) - EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (A, Duplicated), (p, Const), (real(α), Tα), (β, Tβ); atol, rtol) - EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (real(A), Duplicated), (p, Const), (real(α), Tα), (β, Tβ); atol, rtol) - end - end - end -end diff --git a/test/enzyme-indexmanipulations-unit/insertunit.jl b/test/enzyme-indexmanipulations-unit/insertunit.jl deleted file mode 100644 index 9513d5ee7..000000000 --- a/test/enzyme-indexmanipulations-unit/insertunit.jl +++ /dev/null @@ -1,26 +0,0 @@ -using Test, TestExtras -using TensorKit -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -if VERSION > v"1.11.0-rc" # https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @timedtestset verbose = true "Enzyme - Index Manipulations (insertunit):" begin - @timedtestset verbose = true "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, TA in (Duplicated,) - atol = default_tol(T) - rtol = default_tol(T) - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - @testset for insertunit in (insertleftunit, insertrightunit) - EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(1), Const); atol, rtol) - EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(4), Const); atol, rtol) - EnzymeTestUtils.test_reverse(insertunit, TA, (A', TA), (Val(2), Const); atol, rtol) - EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(1), Const); atol, rtol, fkwargs = (copy = false,)) - EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(2), Const); atol, rtol, fkwargs = (copy = true,)) - EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(3), Const); atol, rtol, fkwargs = (copy = false, dual = true, conj = true)) - EnzymeTestUtils.test_reverse(insertunit, TA, (A', TA), (Val(3), Const); atol, rtol, fkwargs = (copy = false, dual = true, conj = true)) - end - end - end -end diff --git a/test/enzyme-indexmanipulations-unit/removeunit.jl b/test/enzyme-indexmanipulations-unit/removeunit.jl deleted file mode 100644 index 2cd632a90..000000000 --- a/test/enzyme-indexmanipulations-unit/removeunit.jl +++ /dev/null @@ -1,22 +0,0 @@ -using Test, TestExtras -using TensorKit -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -if VERSION > v"1.11.0-rc" # https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @timedtestset verbose = true "Enzyme - Index Manipulations (removeunit):" begin - @timedtestset verbose = true "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes, TB in (Duplicated,) - atol = default_tol(T) - rtol = default_tol(T) - A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - for i in 1:2 - B = insertleftunit(A, i; dual = rand(Bool)) - EnzymeTestUtils.test_reverse(removeunit, TB, (B, TB), (Val(i), Const); atol, rtol, fkwargs = (copy = false,)) - EnzymeTestUtils.test_reverse(removeunit, TB, (B, TB), (Val(i), Const); atol, rtol, fkwargs = (copy = true,)) - end - end - end -end diff --git a/test/enzyme-linalg/inv.jl b/test/enzyme-linalg/inv.jl deleted file mode 100644 index 35bd074fb..000000000 --- a/test/enzyme-linalg/inv.jl +++ /dev/null @@ -1,33 +0,0 @@ -using Test, TestExtras -using TensorKit -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" -TDs = is_ci ? (Duplicated,) : (Const, Duplicated) - -@timedtestset "Enzyme - LinearAlgebra (inv):" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - @testset "inv: TD $TD" for TD in TDs - D1 = randn(T, V[1] ← V[1]) - EnzymeTestUtils.test_reverse(inv, TD, (D1, TD); atol, rtol) - EnzymeTestUtils.test_forward(inv, TD, (D1, TD); atol, rtol) - if !is_ci - D2 = randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]) - EnzymeTestUtils.test_reverse(inv, TD, (D2, TD); atol, rtol) - EnzymeTestUtils.test_forward(inv, TD, (D2, TD); atol, rtol) - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @static if VERSION ≥ v"1.11.0-rc" - D3 = randn(T, V[1] ⊗ V[2] ⊗ V[3] ← V[1] ⊗ V[2] ⊗ V[3]) - EnzymeTestUtils.test_reverse(inv, TD, (D3, TD); atol, rtol) - EnzymeTestUtils.test_forward(inv, TD, (D3, TD); atol, rtol) - end - end - end - end -end diff --git a/test/enzyme-linalg/mul.jl b/test/enzyme-linalg/mul.jl deleted file mode 100644 index 1250df342..000000000 --- a/test/enzyme-linalg/mul.jl +++ /dev/null @@ -1,70 +0,0 @@ -using Test, TestExtras -using TensorKit -using VectorInterface -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" - -@timedtestset verbose = true "Enzyme - LinearAlgebra (mul):" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @static if VERSION < v"1.11.0-rc" - C = randn(T, V[1] ⊗ V[2] ← (V[4] ⊗ V[5])') - else - C = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - end - A = randn(T, codomain(C) ← V[5]' ⊗ V[4]') - B = randn(T, domain(A) ← domain(C)) - zero_αβs = ((Zero(), Zero()), (randn(T), Zero()), (Zero(), randn(T))) - αβs = !is_ci ? vcat(zero_αβs..., (randn(T), randn(T))) : ((randn(T), randn(T)),) - for TC in (Duplicated,), TA in (Duplicated,), TB in (Duplicated,) - for (α, β) in αβs - rTαs = if α === Zero() - (Const,) - elseif !is_ci - (Active, Const) - else - (Active,) - end - rTβs = if β === Zero() - (Const,) - elseif !is_ci - (Active, Const) - else - (Active,) - end - for Tα in rTαs, Tβ in rTβs - EnzymeTestUtils.test_reverse(mul!, TC, (C, TC), (A, TA), (B, TB), (α, Tα), (β, Tβ); atol, rtol, testset_name = "mul! reverse Tα $Tα, Tβ $Tβ") - end - fTαs = if α === Zero() - (Const,) - elseif !is_ci - (Duplicated, Const) - else - (Duplicated,) - end - fTβs = if β === Zero() - (Const,) - elseif !is_ci - (Duplicated, Const) - else - (Duplicated,) - end - for Tα in fTαs, Tβ in fTβs - EnzymeTestUtils.test_forward(mul!, TC, (C, TC), (A, TA), (B, TB), (α, Tα), (β, Tβ); atol, rtol, testset_name = "mul! forward Tα $Tα, Tβ $Tβ") - end - end - if !is_ci - EnzymeTestUtils.test_reverse(mul!, TC, (C, TC), (A, TA), (B, TB); atol, rtol, testset_name = "mul! reverse no α no β") - EnzymeTestUtils.test_forward(mul!, TC, (C, TC), (A, TA), (B, TB); atol, rtol, testset_name = "mul! forward no α no β") - end - end - end -end diff --git a/test/enzyme-linalg/norm.jl b/test/enzyme-linalg/norm.jl deleted file mode 100644 index 504e51884..000000000 --- a/test/enzyme-linalg/norm.jl +++ /dev/null @@ -1,32 +0,0 @@ -using Test, TestExtras -using TensorKit -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" -rRTs = is_ci ? (Active,) : (Const, Active) -fRTs = is_ci ? (Duplicated,) : (Const, Duplicated) - -@timedtestset verbose = true "Enzyme - LinearAlgebra (norm):" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T), TC $TC" for V in spacelist, T in eltypes, TC in (Const, Duplicated) - atol = default_tol(T) - rtol = default_tol(T) - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @static if VERSION < v"1.11.0-rc" - C = randn(T, V[1] ⊗ V[2] ← (V[4] ⊗ V[5])') - else - C = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') - end - for RT in rRTs - EnzymeTestUtils.test_reverse(norm, RT, (C, TC), (2, Const); atol, rtol) - EnzymeTestUtils.test_reverse(norm, RT, (C', TC), (2, Const); atol, rtol) - end - for RT in fRTs - EnzymeTestUtils.test_forward(norm, RT, (C, TC), (2, Const); atol, rtol) - EnzymeTestUtils.test_forward(norm, RT, (C', TC), (2, Const); atol, rtol) - end - end -end diff --git a/test/enzyme-linalg/tr.jl b/test/enzyme-linalg/tr.jl deleted file mode 100644 index f42e02ee1..000000000 --- a/test/enzyme-linalg/tr.jl +++ /dev/null @@ -1,39 +0,0 @@ -using Test, TestExtras -using TensorKit -using Enzyme, EnzymeTestUtils -using Random - -is_ci = get(ENV, "CI", "false") == "true" - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -rRTs = is_ci ? (Active,) : (Const, Active) -fRTs = is_ci ? (Duplicated,) : (Const, Duplicated) -TDs = is_ci ? (Duplicated,) : (Const, Duplicated) - -@timedtestset verbose = true "Enzyme - LinearAlgebra (tr):" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - D1 = randn(T, V[1] ← V[1]) - D2 = randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]) - D3 = randn(T, V[1] ⊗ V[2] ⊗ V[3] ← V[1] ⊗ V[2] ⊗ V[3]) - @testset "tr reverse: RT $RT, TD $TD" for RT in rRTs, TD in TDs - EnzymeTestUtils.test_reverse(tr, RT, (D1, TD); atol, rtol) - EnzymeTestUtils.test_reverse(tr, RT, (D2, TD); atol, rtol) - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @static if VERSION ≥ v"1.11.0-rc" - EnzymeTestUtils.test_reverse(tr, RT, (D3, TD); atol, rtol) - end - end - @testset "tr forward: RT $RT, TD $TD" for RT in fRTs, TD in TDs - EnzymeTestUtils.test_forward(tr, RT, (D1, TD); atol, rtol) - EnzymeTestUtils.test_forward(tr, RT, (D2, TD); atol, rtol) - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - @static if VERSION ≥ v"1.11.0-rc" - EnzymeTestUtils.test_forward(tr, RT, (D3, TD); atol, rtol) - end - end - end -end diff --git a/test/enzyme-tensoroperations/contract.jl b/test/enzyme-tensoroperations/contract.jl deleted file mode 100644 index 9829a11f3..000000000 --- a/test/enzyme-tensoroperations/contract.jl +++ /dev/null @@ -1,140 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using VectorInterface: One, Zero -using Enzyme, EnzymeTestUtils - -is_ci = get(ENV, "CI", "false") == "true" - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -if !(is_ci && Sys.iswindows() && VERSION < v"1.11.0-rc") - @timedtestset "Enzyme - TensorOperations" begin - @timedtestset verbose = true "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - symmetricbraiding = BraidingStyle(sectortype(eltype(V))) isa SymmetricBraiding - symmetricbraiding && @timedtestset "tensorcontract!" begin - d = 0 - local V1, V2, V3 - # retry a couple times to make sure there are at least some nonzero elements - for _ in 1:10 - k1 = rand(0:3) - k2 = rand(0:2) - k3 = rand(0:2) - V1 = prod(v -> rand(Bool) ? v' : v, rand(V, k1); init = one(V[1])) - V2 = prod(v -> rand(Bool) ? v' : v, rand(V, k2); init = one(V[1])) - V3 = prod(v -> rand(Bool) ? v' : v, rand(V, k3); init = one(V[1])) - d = min(dim(V1 ← V2), dim(V1' ← V2), dim(V2 ← V3), dim(V2' ← V3)) - d > 0 && break - end - ipA = randindextuple(length(V1) + length(V2)) - pA = _repartition(invperm(linearize(ipA)), length(V1)) - ipB = randindextuple(length(V2) + length(V3)) - pB = _repartition(invperm(linearize(ipB)), length(V2)) - pAB = randindextuple(length(V1) + length(V3)) - - α = randn(T) - β = randn(T) - V2_conj = prod(conj, V2; init = one(V[1])) - A = randn(T, permute(V1 ← V2, ipA)) - B = randn(T, permute(V2 ← V3, ipB)) - C = randn!( - TensorOperations.tensoralloc_contract( - T, A, pA, false, B, pB, false, pAB, Val(false) - ) - ) - - αβs = is_ci ? (((α, Active), (β, Active)),) : Iterators.product(((One(), Const), (α, Const), (α, Active)), ((Zero(), Const), (β, Const), (β, Active))) - for (α_, β_) in αβs - EnzymeTestUtils.test_reverse( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (A, Duplicated), (pA, Const), - (B, Duplicated), (pB, Const), (pAB, Const), - α_, β_, - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! reverse α $α_ β $β_", - ) - end - αβs = is_ci ? (((α, Duplicated), (β, Duplicated)),) : Iterators.product(((One(), Const), (α, Const), (α, Duplicated)), ((Zero(), Const), (β, Const), (β, Duplicated))) - for (α_, β_) in αβs - EnzymeTestUtils.test_forward( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (A, Duplicated), (pA, Const), - (B, Duplicated), (pB, Const), (pAB, Const), - α_, β_, - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! forward α $α_ β $β_", - ) - end - if !(T <: Real) && !is_ci - EnzymeTestUtils.test_reverse( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (A, Duplicated), (pA, Const), - (B, Duplicated), (pB, Const), (pAB, Const), - (real(α), Active), (real(β), Active), - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! reverse real(α) real(β)", - ) - EnzymeTestUtils.test_reverse( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (real(A), Duplicated), (pA, Const), - (B, Duplicated), (pB, Const), (pAB, Const), - (real(α), Active), (real(β), Active), - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! reverse real(A) real(α) real(β)", - ) - EnzymeTestUtils.test_reverse( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (A, Duplicated), (pA, Const), - (real(B), Duplicated), (pB, Const), (pAB, Const), - (real(α), Active), (real(β), Active), - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! reverse real(B) real(α) real(β)", - ) - EnzymeTestUtils.test_forward( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (A, Duplicated), (pA, Const), - (B, Duplicated), (pB, Const), (pAB, Const), - (real(α), Active), (real(β), Active), - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! forward real(α) real(β)", - ) - EnzymeTestUtils.test_forward( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (real(A), Duplicated), (pA, Const), - (B, Duplicated), (pB, Const), (pAB, Const), - (real(α), Active), (real(β), Active), - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! forward real(A) real(α) real(β)", - ) - EnzymeTestUtils.test_forward( - TensorKit.blas_contract!, Duplicated, - (copy(C), Duplicated), (A, Duplicated), (pA, Const), - (real(B), Duplicated), (pB, Const), (pAB, Const), - (real(α), Active), (real(β), Active), - (TensorOperations.DefaultBackend(), Const), - (TensorOperations.DefaultAllocator(), Const); - atol, rtol, - testset_name = "blas_contract! forward real(B) real(α) real(β)", - ) - end - end - end - end -end diff --git a/test/enzyme-tensoroperations/trace.jl b/test/enzyme-tensoroperations/trace.jl deleted file mode 100644 index 5a805d1ac..000000000 --- a/test/enzyme-tensoroperations/trace.jl +++ /dev/null @@ -1,62 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using VectorInterface: One, Zero -using Enzyme, EnzymeTestUtils - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -is_ci = get(ENV, "CI", "false") == "true" -rTαs = is_ci ? (Active,) : (Const, Active) -rTβs = is_ci ? (Active,) : (Const, Active) -fTαs = is_ci ? (Duplicated,) : (Const, Duplicated) -fTβs = is_ci ? (Duplicated,) : (Const, Duplicated) -TCs = is_ci ? (Duplicated,) : (Const, Duplicated) -TAs = is_ci ? (Duplicated,) : (Const, Duplicated) - -if !(is_ci && Sys.iswindows() && VERSION < v"1.11.0-rc") - @timedtestset "Enzyme - TensorOperations (trace)" begin - @timedtestset verbose = true "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - symmetricbraiding = BraidingStyle(sectortype(eltype(V))) isa SymmetricBraiding - symmetricbraiding && @timedtestset "trace_permute!" begin - k1 = rand(0:2) - k2 = rand(1:2) - V1 = map(v -> rand(Bool) ? v' : v, rand(V, k1)) - V2 = map(v -> rand(Bool) ? v' : v, rand(V, k2)) - - (_p, _q) = randindextuple(k1 + 2 * k2, k1) - p = _repartition(_p, rand(0:k1)) - q = _repartition(_q, k2) - ip = _repartition(invperm(linearize((_p, _q))), rand(0:(k1 + 2 * k2))) - A = randn(T, permute(prod(V1) ⊗ prod(V2) ← prod(V2), ip)) - - α = randn(T) - β = randn(T) - C = randn!(TensorOperations.tensoralloc_add(T, A, p, false, Val(false))) - for TC in TCs, TA in TAs - for Tα in rTαs, Tβ in rTβs - EnzymeTestUtils.test_reverse( - TensorKit.trace_permute!, TC, - (copy(C), TC), (A, TA), (p, Const), (q, Const), - (α, Tα), (β, Tβ), (TensorOperations.DefaultBackend(), Const); - atol, rtol, - testset_name = "trace_permute! reverse TC $TC TA $TA Tα $Tα Tβ $Tβ", - ) - end - for Tα in fTαs, Tβ in fTβs - EnzymeTestUtils.test_forward( - TensorKit.trace_permute!, TC, - (copy(C), TC), (A, TA), (p, Const), (q, Const), - (α, Tα), (β, Tβ), (TensorOperations.DefaultBackend(), Const); - atol, rtol, - testset_name = "trace_permute! forward TC $TC TA $TA Tα $Tα Tβ $Tβ", - ) - end - end - end - end - end -end diff --git a/test/enzyme-vectorinterface/add.jl b/test/enzyme-vectorinterface/add.jl deleted file mode 100644 index 5d44b2830..000000000 --- a/test/enzyme-vectorinterface/add.jl +++ /dev/null @@ -1,51 +0,0 @@ -using Test, TestExtras -using TensorKit, Enzyme, EnzymeTestUtils -using TensorOperations -using Random - -#spacelist = ad_spacelist(fast_tests) -spacelist = [ad_spacelist(fast_tests)[1]] -eltypes = (Float64, ComplexF64) - -@testset "Enzyme - VectorInterface (add!) $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - - α = randn(T) - β = randn(T) - - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - if VERSION < v"1.11.0-rc" && sectortype(eltype(V)) == Trivial - CV = V[1] ⊗ V[2] ← V[4] ⊗ V[5] - else - CV = V[1] ⊗ V[2] ← V[3] ⊗ V[4] ⊗ V[5] - end - C = randn(T, CV) - A = randn(T, CV) - for TC in (Duplicated,), TA in (Duplicated,) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_reverse(add!, TC, (C, TC), (A, TA); atol, rtol, testset_name = "add! reverse TC $TC TA $TA no α no β") - EnzymeTestUtils.test_forward(add!, TC, (C, TC), (A, TA); atol, rtol, testset_name = "add! forward TC $TC TA $TA no α no β") - for Tα in (Active, Const) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_reverse(add!, TC, (C, TC), (A, TA), (α, Tα); atol, rtol, testset_name = "add! reverse TC $TC TA $TA Tα $Tα no β") - for Tβ in (Active, Const) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_reverse(add!, TC, (C, TC), (A, TA), (α, Tα), (β, Tβ); atol, rtol, testset_name = "add! reverse TC $TC TA $TA Tα $Tα Tβ $Tβ") - end - end - for Tα in (Duplicated, Const) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_forward(add!, TC, (C, TC), (A, TA), (α, Tα); atol, rtol, testset_name = "add! forward TC $TC TA $TA Tα $Tα no β") - for Tβ in (Duplicated, Const) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_forward(add!, TC, (C, TC), (A, TA), (α, Tα), (β, Tβ); atol, rtol, testset_name = "add! forward TC $TC TA $TA Tα $Tα Tβ $Tβ") - end - end - end -end diff --git a/test/enzyme-vectorinterface/inner.jl b/test/enzyme-vectorinterface/inner.jl deleted file mode 100644 index 5df4a8017..000000000 --- a/test/enzyme-vectorinterface/inner.jl +++ /dev/null @@ -1,31 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using Enzyme, EnzymeTestUtils -using Random, FiniteDifferences - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@testset "Enzyme - VectorInterface" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - @testset for TC in (Duplicated,), TA in (Duplicated,), f in (identity, adjoint) - atol = default_tol(T) - rtol = default_tol(T) - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - if VERSION < v"1.11.0-rc" && sectortype(eltype(V)) == Trivial - CV = V[1] ⊗ V[2] ← V[4] ⊗ V[5] - else - CV = V[1] ⊗ V[2] ← V[3] ⊗ V[4] ⊗ V[5] - end - C = randn(T, CV) - A = randn(T, CV) - for RT in (Active, Const) - EnzymeTestUtils.test_reverse(inner, RT, (f(C), TC), (f(A), TA); atol, rtol) - end - for RT in (Duplicated, Const) - EnzymeTestUtils.test_forward(inner, RT, (f(C), TC), (f(A), TA); atol, rtol) - end - end - end -end diff --git a/test/enzyme-vectorinterface/scale.jl b/test/enzyme-vectorinterface/scale.jl deleted file mode 100644 index 8d3f109d5..000000000 --- a/test/enzyme-vectorinterface/scale.jl +++ /dev/null @@ -1,46 +0,0 @@ -using Test, TestExtras -using TensorKit -using TensorOperations -using Enzyme, EnzymeTestUtils -using Random - -spacelist = ad_spacelist(fast_tests) -eltypes = (Float64, ComplexF64) - -@testset "Enzyme - VectorInterface (scale!)" begin - @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes - atol = default_tol(T) - rtol = default_tol(T) - α = randn(T) - # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 - if VERSION < v"1.11.0-rc" && sectortype(eltype(V)) == Trivial - CV = V[1] ⊗ V[2] ← V[4] ⊗ V[5] - else - CV = V[1] ⊗ V[2] ← V[3] ⊗ V[4] ⊗ V[5] - end - @testset for TC in (Duplicated,) - for Tα in (Active, Const) - C = randn(T, CV) - EnzymeTestUtils.test_reverse(scale!, TC, (C, TC), (α, Tα); atol, rtol) - C = randn(T, CV) - EnzymeTestUtils.test_reverse(scale!, TC, (C', TC), (α, Tα); atol, rtol) - @testset for TA in (Duplicated,), (fc, fa) in ((identity, identity), (adjoint, adjoint)) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_reverse(scale!, TC, (fc(C), TC), (fa(A), TA), (α, Tα); atol, rtol) - end - end - for Tα in (Duplicated, Const) - C = randn(T, CV) - EnzymeTestUtils.test_forward(scale!, TC, (C, TC), (α, Tα); atol, rtol) - C = randn(T, CV) - EnzymeTestUtils.test_forward(scale!, TC, (C', TC), (α, Tα); atol, rtol) - @testset for TA in (Duplicated,), (fc, fa) in ((identity, identity), (adjoint, adjoint)) - C = randn(T, CV) - A = randn(T, CV) - EnzymeTestUtils.test_forward(scale!, TC, (fc(C), TC), (fa(A), TA), (α, Tα); atol, rtol) - end - end - end - end -end diff --git a/test/enzyme/indexmanipulations.jl b/test/enzyme/indexmanipulations.jl new file mode 100644 index 000000000..8e47e4c89 --- /dev/null +++ b/test/enzyme/indexmanipulations.jl @@ -0,0 +1,102 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +is_ci = get(ENV, "CI", "false") == "true" + +Tαs = is_ci ? (Active,) : (Active, Const) +Tβs = is_ci ? (Active,) : (Active, Const) + +@timedtestset "Enzyme - Index Manipulations: $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + has_braiding = BraidingStyle(sectortype(eltype(V))) isa HasBraiding + symmetric_braiding = BraidingStyle(sectortype(eltype(V))) isa SymmetricBraiding + Vstr = TensorKit.type_repr(sectortype(eltype(V))) + atol = default_tol(T) + rtol = default_tol(T) + if VERSION >= v"1.11.0-rc" # segfault issues on 1.10 + symmetric_braiding && @timedtestset "permute! Tα $Tα, Tβ $Tβ" for Tα in Tαs, Tβ in Tβs + A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + α = randn(T) + β = randn(T) + p = randindextuple(numind(A)) + C = randn!(permute(A, p)) + EnzymeTestUtils.test_reverse(TensorKit.permute!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (α, Tα), (β, Tβ); atol, rtol) + end + end + if VERSION > v"1.11.0-rc" # https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + @timedtestset "transpose!" begin + A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + α = randn(T) + β = randn(T) + + # repeat a couple times to get some distribution of arrows + p = randcircshift(numout(A), numin(A)) + C = randn!(transpose(A, p)) + !is_ci && EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (A, Duplicated), (p, Const), (One(), Const), (Zero(), Const); atol, rtol) + @testset for Tα in Tαs, Tβ in Tβs + EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (A, Duplicated), (p, Const), (α, Tα), (β, Tβ); atol, rtol) + if !(T <: Real) && !is_ci + EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (real(A), Duplicated), (p, Const), (α, Tα), (β, Tβ); atol, rtol) + EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (A, Duplicated), (p, Const), (real(α), Tα), (β, Tβ); atol, rtol) + EnzymeTestUtils.test_reverse(TensorKit.transpose!, Duplicated, (copy(C), Duplicated), (real(A), Duplicated), (p, Const), (real(α), Tα), (β, Tβ); atol, rtol) + end + end + end + end + if !Sys.iswindows() && VERSION > v"1.11.0-rc" + @timedtestset "braid! Tα $Tα Tβ $Tβ" for Tα in Tαs, Tβ in Tβs + if has_braiding + A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + α = randn(T) + β = randn(T) + p = randcircshift(numout(A), numin(A)) + levels = Tuple(randperm(numind(A))) + C = randn!(transpose(A, p)) + EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (levels, Const), (α, Tα), (β, Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") + if !(T <: Real) && !is_ci + EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (real(A), Duplicated), (p, Const), (levels, Const), (α, Tα), (β, Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") + EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (levels, Const), (real(α), Tα), (β, Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") + EnzymeTestUtils.test_reverse(TensorKit.braid!, Duplicated, (C, Duplicated), (A, Duplicated), (p, Const), (levels, Const), (real(α), Tα), (real(β), Tβ); atol, rtol, testset_name = "braid! V $Vstr Tα $Tα Tβ $Tβ") + end + end + end + end + if !Sys.iswindows() && VERSION > v"1.11.0-rc" + has_braiding && @timedtestset "flip_n_twist! TA ($TA)" for TA in (Duplicated,) + A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + if !(T <: Real && !(sectorscalartype(sectortype(A)) <: Real)) + EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), (1, Const); atol, rtol, fkwargs = (inv = false,)) + EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), ([1, 3], Const); atol, rtol, fkwargs = (inv = true,)) + EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), (1, Const); atol, rtol) + EnzymeTestUtils.test_reverse(twist!, TA, (copy(A), TA), ([1, 3], Const); atol, rtol) + end + EnzymeTestUtils.test_reverse(flip, TA, (A, TA), (1, Const); atol, rtol, fkwargs = (inv = false,)) + EnzymeTestUtils.test_reverse(flip, TA, (A, TA), [1, 3]; atol, rtol, fkwargs = (inv = true,)) + EnzymeTestUtils.test_reverse(flip, TA, (A, TA), (1, Const); atol, rtol) + EnzymeTestUtils.test_reverse(flip, TA, (A, TA), ([1, 3], Const); atol, rtol) + end + end + + @timedtestset "insert and remove units TA ($TA)" for TA in (Duplicated,) + A = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + @testset for insertunit in (insertleftunit, insertrightunit) + EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(1), Const); atol, rtol) + EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(4), Const); atol, rtol) + EnzymeTestUtils.test_reverse(insertunit, TA, (A', TA), (Val(2), Const); atol, rtol) + EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(1), Const); atol, rtol, fkwargs = (copy = false,)) + EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(2), Const); atol, rtol, fkwargs = (copy = true,)) + EnzymeTestUtils.test_reverse(insertunit, TA, (A, TA), (Val(3), Const); atol, rtol, fkwargs = (copy = false, dual = true, conj = true)) + EnzymeTestUtils.test_reverse(insertunit, TA, (A', TA), (Val(3), Const); atol, rtol, fkwargs = (copy = false, dual = true, conj = true)) + end + for i in 1:2 + B = insertleftunit(A, i; dual = rand(Bool)) + EnzymeTestUtils.test_reverse(removeunit, TB, (B, TB), (Val(i), Const); atol, rtol, fkwargs = (copy = false,)) + EnzymeTestUtils.test_reverse(removeunit, TB, (B, TB), (Val(i), Const); atol, rtol, fkwargs = (copy = true,)) + end + end +end diff --git a/test/enzyme/linalg.jl b/test/enzyme/linalg.jl new file mode 100644 index 000000000..ef7dec4d3 --- /dev/null +++ b/test/enzyme/linalg.jl @@ -0,0 +1,141 @@ +using Test, TestExtras +using TensorKit +using VectorInterface +using Enzyme, EnzymeTestUtils +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +is_ci = get(ENV, "CI", "false") == "true" + +@timedtestset verbose = true "Enzyme - LinearAlgebra (mul):" begin + @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + atol = default_tol(T) + rtol = default_tol(T) + + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + @static if VERSION < v"1.11.0-rc" + C = randn(T, V[1] ⊗ V[2] ← (V[4] ⊗ V[5])') + else + C = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + end + A = randn(T, codomain(C) ← V[5]' ⊗ V[4]') + B = randn(T, domain(A) ← domain(C)) + zero_αβs = ((Zero(), Zero()), (randn(T), Zero()), (Zero(), randn(T))) + αβs = !is_ci ? vcat(zero_αβs..., (randn(T), randn(T))) : ((randn(T), randn(T)),) + for TC in (Duplicated,), TA in (Duplicated,), TB in (Duplicated,) + for (α, β) in αβs + rTαs = [] + α === Zero() || push!(rTαs, Active) + (α === Zero() || !is_ci) && push!(rTαs, Const) + rTβs = if β === Zero() + (Const,) + elseif !is_ci + (Active, Const) + else + (Active,) + end + for Tα in rTαs, Tβ in rTβs + EnzymeTestUtils.test_reverse(mul!, TC, (C, TC), (A, TA), (B, TB), (α, Tα), (β, Tβ); atol, rtol, testset_name = "mul! reverse Tα $Tα, Tβ $Tβ") + end + fTαs = if α === Zero() + (Const,) + elseif !is_ci + (Duplicated, Const) + else + (Duplicated,) + end + fTβs = if β === Zero() + (Const,) + elseif !is_ci + (Duplicated, Const) + else + (Duplicated,) + end + for Tα in fTαs, Tβ in fTβs + EnzymeTestUtils.test_forward(mul!, TC, (C, TC), (A, TA), (B, TB), (α, Tα), (β, Tβ); atol, rtol, testset_name = "mul! forward Tα $Tα, Tβ $Tβ") + end + end + if !is_ci + EnzymeTestUtils.test_reverse(mul!, TC, (C, TC), (A, TA), (B, TB); atol, rtol, testset_name = "mul! reverse no α no β") + EnzymeTestUtils.test_forward(mul!, TC, (C, TC), (A, TA), (B, TB); atol, rtol, testset_name = "mul! forward no α no β") + end + end + end +end + +rRTs = is_ci ? (Active,) : (Const, Active) +fRTs = is_ci ? (Duplicated,) : (Const, Duplicated) + +@timedtestset verbose = true "Enzyme - LinearAlgebra (norm):" begin + @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T), TC $TC" for V in spacelist, T in eltypes, TC in (Const, Duplicated) + atol = default_tol(T) + rtol = default_tol(T) + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + @static if VERSION < v"1.11.0-rc" + C = randn(T, V[1] ⊗ V[2] ← (V[4] ⊗ V[5])') + else + C = randn(T, V[1] ⊗ V[2] ← (V[3] ⊗ V[4] ⊗ V[5])') + end + for RT in rRTs + EnzymeTestUtils.test_reverse(norm, RT, (C, TC), (2, Const); atol, rtol) + EnzymeTestUtils.test_reverse(norm, RT, (C', TC), (2, Const); atol, rtol) + end + for RT in fRTs + EnzymeTestUtils.test_forward(norm, RT, (C, TC), (2, Const); atol, rtol) + EnzymeTestUtils.test_forward(norm, RT, (C', TC), (2, Const); atol, rtol) + end + end +end + +TDs = is_ci ? (Duplicated,) : (Const, Duplicated) + +@timedtestset "Enzyme - LinearAlgebra (inv):" begin + @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + atol = default_tol(T) + rtol = default_tol(T) + @testset "inv: TD $TD" for TD in TDs + D1 = randn(T, V[1] ← V[1]) + EnzymeTestUtils.test_reverse(inv, TD, (D1, TD); atol, rtol) + EnzymeTestUtils.test_forward(inv, TD, (D1, TD); atol, rtol) + if !is_ci + D2 = randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]) + EnzymeTestUtils.test_reverse(inv, TD, (D2, TD); atol, rtol) + EnzymeTestUtils.test_forward(inv, TD, (D2, TD); atol, rtol) + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + @static if VERSION ≥ v"1.11.0-rc" + D3 = randn(T, V[1] ⊗ V[2] ⊗ V[3] ← V[1] ⊗ V[2] ⊗ V[3]) + EnzymeTestUtils.test_reverse(inv, TD, (D3, TD); atol, rtol) + EnzymeTestUtils.test_forward(inv, TD, (D3, TD); atol, rtol) + end + end + end + end +end + +@timedtestset verbose = true "Enzyme - LinearAlgebra (tr):" begin + @timedtestset "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + atol = default_tol(T) + rtol = default_tol(T) + D1 = randn(T, V[1] ← V[1]) + D2 = randn(T, V[1] ⊗ V[2] ← V[1] ⊗ V[2]) + D3 = randn(T, V[1] ⊗ V[2] ⊗ V[3] ← V[1] ⊗ V[2] ⊗ V[3]) + @testset "tr reverse: RT $RT, TD $TD" for RT in rRTs, TD in TDs + EnzymeTestUtils.test_reverse(tr, RT, (D1, TD); atol, rtol) + EnzymeTestUtils.test_reverse(tr, RT, (D2, TD); atol, rtol) + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + @static if VERSION ≥ v"1.11.0-rc" + EnzymeTestUtils.test_reverse(tr, RT, (D3, TD); atol, rtol) + end + end + @testset "tr forward: RT $RT, TD $TD" for RT in fRTs, TD in TDs + EnzymeTestUtils.test_forward(tr, RT, (D1, TD); atol, rtol) + EnzymeTestUtils.test_forward(tr, RT, (D2, TD); atol, rtol) + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + @static if VERSION ≥ v"1.11.0-rc" + EnzymeTestUtils.test_forward(tr, RT, (D3, TD); atol, rtol) + end + end + end +end diff --git a/test/enzyme/tensoroperations.jl b/test/enzyme/tensoroperations.jl new file mode 100644 index 000000000..0293a5070 --- /dev/null +++ b/test/enzyme/tensoroperations.jl @@ -0,0 +1,174 @@ +using Test, TestExtras +using TensorKit +using TensorOperations +using VectorInterface: One, Zero +using Enzyme, EnzymeTestUtils + +is_ci = get(ENV, "CI", "false") == "true" + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@timedtestset "Enzyme - TensorOperations" begin + @timedtestset verbose = true "$(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + atol = default_tol(T) + rtol = default_tol(T) + symmetricbraiding = BraidingStyle(sectortype(eltype(V))) isa SymmetricBraiding + symmetricbraiding && @timedtestset "tensorcontract!" begin + d = 0 + local V1, V2, V3 + # retry a couple times to make sure there are at least some nonzero elements + for _ in 1:10 + k1 = rand(0:3) + k2 = rand(0:2) + k3 = rand(0:2) + V1 = prod(v -> rand(Bool) ? v' : v, rand(V, k1); init = one(V[1])) + V2 = prod(v -> rand(Bool) ? v' : v, rand(V, k2); init = one(V[1])) + V3 = prod(v -> rand(Bool) ? v' : v, rand(V, k3); init = one(V[1])) + d = min(dim(V1 ← V2), dim(V1' ← V2), dim(V2 ← V3), dim(V2' ← V3)) + d > 0 && break + end + ipA = randindextuple(length(V1) + length(V2)) + pA = _repartition(invperm(linearize(ipA)), length(V1)) + ipB = randindextuple(length(V2) + length(V3)) + pB = _repartition(invperm(linearize(ipB)), length(V2)) + pAB = randindextuple(length(V1) + length(V3)) + + α = randn(T) + β = randn(T) + V2_conj = prod(conj, V2; init = one(V[1])) + A = randn(T, permute(V1 ← V2, ipA)) + B = randn(T, permute(V2 ← V3, ipB)) + C = randn!( + TensorOperations.tensoralloc_contract( + T, A, pA, false, B, pB, false, pAB, Val(false) + ) + ) + + αβs = is_ci ? (((α, Active), (β, Active)),) : Iterators.product(((One(), Const), (α, Const), (α, Active)), ((Zero(), Const), (β, Const), (β, Active))) + for (α_, β_) in αβs + EnzymeTestUtils.test_reverse( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (A, Duplicated), (pA, Const), + (B, Duplicated), (pB, Const), (pAB, Const), + α_, β_, + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! reverse α $α_ β $β_", + ) + end + αβs = is_ci ? (((α, Duplicated), (β, Duplicated)),) : Iterators.product(((One(), Const), (α, Const), (α, Duplicated)), ((Zero(), Const), (β, Const), (β, Duplicated))) + for (α_, β_) in αβs + EnzymeTestUtils.test_forward( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (A, Duplicated), (pA, Const), + (B, Duplicated), (pB, Const), (pAB, Const), + α_, β_, + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! forward α $α_ β $β_", + ) + end + if !(T <: Real) && !is_ci + EnzymeTestUtils.test_reverse( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (A, Duplicated), (pA, Const), + (B, Duplicated), (pB, Const), (pAB, Const), + (real(α), Active), (real(β), Active), + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! reverse real(α) real(β)", + ) + EnzymeTestUtils.test_reverse( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (real(A), Duplicated), (pA, Const), + (B, Duplicated), (pB, Const), (pAB, Const), + (real(α), Active), (real(β), Active), + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! reverse real(A) real(α) real(β)", + ) + EnzymeTestUtils.test_reverse( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (A, Duplicated), (pA, Const), + (real(B), Duplicated), (pB, Const), (pAB, Const), + (real(α), Active), (real(β), Active), + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! reverse real(B) real(α) real(β)", + ) + EnzymeTestUtils.test_forward( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (A, Duplicated), (pA, Const), + (B, Duplicated), (pB, Const), (pAB, Const), + (real(α), Active), (real(β), Active), + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! forward real(α) real(β)", + ) + EnzymeTestUtils.test_forward( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (real(A), Duplicated), (pA, Const), + (B, Duplicated), (pB, Const), (pAB, Const), + (real(α), Active), (real(β), Active), + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! forward real(A) real(α) real(β)", + ) + EnzymeTestUtils.test_forward( + TensorKit.blas_contract!, Duplicated, + (copy(C), Duplicated), (A, Duplicated), (pA, Const), + (real(B), Duplicated), (pB, Const), (pAB, Const), + (real(α), Active), (real(β), Active), + (TensorOperations.DefaultBackend(), Const), + (TensorOperations.DefaultAllocator(), Const); + atol, rtol, + testset_name = "blas_contract! forward real(B) real(α) real(β)", + ) + end + end + symmetricbraiding && @timedtestset "trace_permute!" begin + k1 = rand(0:2) + k2 = rand(1:2) + V1 = map(v -> rand(Bool) ? v' : v, rand(V, k1)) + V2 = map(v -> rand(Bool) ? v' : v, rand(V, k2)) + + (_p, _q) = randindextuple(k1 + 2 * k2, k1) + p = _repartition(_p, rand(0:k1)) + q = _repartition(_q, k2) + ip = _repartition(invperm(linearize((_p, _q))), rand(0:(k1 + 2 * k2))) + A = randn(T, permute(prod(V1) ⊗ prod(V2) ← prod(V2), ip)) + + α = randn(T) + β = randn(T) + C = randn!(TensorOperations.tensoralloc_add(T, A, p, false, Val(false))) + for TC in TCs, TA in TAs + for Tα in rTαs, Tβ in rTβs + EnzymeTestUtils.test_reverse( + TensorKit.trace_permute!, TC, + (copy(C), TC), (A, TA), (p, Const), (q, Const), + (α, Tα), (β, Tβ), (TensorOperations.DefaultBackend(), Const); + atol, rtol, + testset_name = "trace_permute! reverse TC $TC TA $TA Tα $Tα Tβ $Tβ", + ) + end + for Tα in fTαs, Tβ in fTβs + EnzymeTestUtils.test_forward( + TensorKit.trace_permute!, TC, + (copy(C), TC), (A, TA), (p, Const), (q, Const), + (α, Tα), (β, Tβ), (TensorOperations.DefaultBackend(), Const); + atol, rtol, + testset_name = "trace_permute! forward TC $TC TA $TA Tα $Tα Tβ $Tβ", + ) + end + end + end + end +end diff --git a/test/enzyme/vectorinterface.jl b/test/enzyme/vectorinterface.jl new file mode 100644 index 000000000..1d2e07266 --- /dev/null +++ b/test/enzyme/vectorinterface.jl @@ -0,0 +1,107 @@ +using Test, TestExtras +using TensorKit, Enzyme, EnzymeTestUtils +using TensorOperations +using Random + +spacelist = ad_spacelist(fast_tests) +eltypes = (Float64, ComplexF64) + +@testset "Enzyme - VectorInterface (add!) $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + atol = default_tol(T) + rtol = default_tol(T) + + α = randn(T) + β = randn(T) + + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + if VERSION < v"1.11.0-rc" && sectortype(eltype(V)) == Trivial + CV = V[1] ⊗ V[2] ← V[4] ⊗ V[5] + else + CV = V[1] ⊗ V[2] ← V[3] ⊗ V[4] ⊗ V[5] + end + C = randn(T, CV) + A = randn(T, CV) + for TC in (Duplicated,), TA in (Duplicated,) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_reverse(add!, TC, (C, TC), (A, TA); atol, rtol, testset_name = "add! reverse TC $TC TA $TA no α no β") + EnzymeTestUtils.test_forward(add!, TC, (C, TC), (A, TA); atol, rtol, testset_name = "add! forward TC $TC TA $TA no α no β") + for Tα in (Active, Const) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_reverse(add!, TC, (C, TC), (A, TA), (α, Tα); atol, rtol, testset_name = "add! reverse TC $TC TA $TA Tα $Tα no β") + for Tβ in (Active, Const) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_reverse(add!, TC, (C, TC), (A, TA), (α, Tα), (β, Tβ); atol, rtol, testset_name = "add! reverse TC $TC TA $TA Tα $Tα Tβ $Tβ") + end + end + for Tα in (Duplicated, Const) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_forward(add!, TC, (C, TC), (A, TA), (α, Tα); atol, rtol, testset_name = "add! forward TC $TC TA $TA Tα $Tα no β") + for Tβ in (Duplicated, Const) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_forward(add!, TC, (C, TC), (A, TA), (α, Tα), (β, Tβ); atol, rtol, testset_name = "add! forward TC $TC TA $TA Tα $Tα Tβ $Tβ") + end + end + end +end + +@testset "Enzyme - VectorInterface (scale!) $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + atol = default_tol(T) + rtol = default_tol(T) + α = randn(T) + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + if VERSION < v"1.11.0-rc" && sectortype(eltype(V)) == Trivial + CV = V[1] ⊗ V[2] ← V[4] ⊗ V[5] + else + CV = V[1] ⊗ V[2] ← V[3] ⊗ V[4] ⊗ V[5] + end + @testset for TC in (Duplicated,) + for Tα in (Active, Const) + C = randn(T, CV) + EnzymeTestUtils.test_reverse(scale!, TC, (C, TC), (α, Tα); atol, rtol) + C = randn(T, CV) + EnzymeTestUtils.test_reverse(scale!, TC, (C', TC), (α, Tα); atol, rtol) + @testset for TA in (Duplicated,), (fc, fa) in ((identity, identity), (adjoint, adjoint)) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_reverse(scale!, TC, (fc(C), TC), (fa(A), TA), (α, Tα); atol, rtol) + end + end + for Tα in (Duplicated, Const) + C = randn(T, CV) + EnzymeTestUtils.test_forward(scale!, TC, (C, TC), (α, Tα); atol, rtol) + C = randn(T, CV) + EnzymeTestUtils.test_forward(scale!, TC, (C', TC), (α, Tα); atol, rtol) + @testset for TA in (Duplicated,), (fc, fa) in ((identity, identity), (adjoint, adjoint)) + C = randn(T, CV) + A = randn(T, CV) + EnzymeTestUtils.test_forward(scale!, TC, (fc(C), TC), (fa(A), TA), (α, Tα); atol, rtol) + end + end + end +end + +@testset "Enzyme - VectorInterface (inner) $(TensorKit.type_repr(sectortype(eltype(V)))) ($T)" for V in spacelist, T in eltypes + @testset for TC in (Duplicated,), TA in (Duplicated,), f in (identity, adjoint) + atol = default_tol(T) + rtol = default_tol(T) + # see https://github.com/QuantumKitHub/TensorKit.jl/issues/457 + if VERSION < v"1.11.0-rc" && sectortype(eltype(V)) == Trivial + CV = V[1] ⊗ V[2] ← V[4] ⊗ V[5] + else + CV = V[1] ⊗ V[2] ← V[3] ⊗ V[4] ⊗ V[5] + end + C = randn(T, CV) + A = randn(T, CV) + for RT in (Active, Const) + EnzymeTestUtils.test_reverse(inner, RT, (f(C), TC), (f(A), TA); atol, rtol) + end + for RT in (Duplicated, Const) + EnzymeTestUtils.test_forward(inner, RT, (f(C), TC), (f(A), TA); atol, rtol) + end + end +end