Skip to content

Commit

Permalink
Testsuite @planar (#76)
Browse files Browse the repository at this point in the history
* Add Trivial anyon

* SpaceMismatches print more information

* Add `checkcontractible` for TensorMaps

* Add planar tests

* Add `tensorcost`
  • Loading branch information
lkdvos authored and Jutho committed Aug 12, 2023
1 parent 866e5e0 commit 951d341
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 2 deletions.
32 changes: 32 additions & 0 deletions src/sectors/anyons.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
# PlanarTrivial
"""
struct PlanarTrivial <: Sector
PlanarTrivial()
Represents a trivial anyon sector, i.e. a trivial sector without braiding. This is mostly
useful for testing.
"""
struct PlanarTrivial <: Sector end

Base.IteratorSize(::Type{SectorValues{PlanarTrivial}}) = HasLength()
Base.length(::SectorValues{PlanarTrivial}) = 1
Base.iterate(::SectorValues{PlanarTrivial}, i = 0) = i == 0 ? (PlanarTrivial(), 1) : nothing
function Base.getindex(::SectorValues{PlanarTrivial}, i::Int)
return i == 1 ? PlanarTrivial() :
throw(BoundsError(values(PlanarTrivial), i))
end
findindex(::SectorValues{PlanarTrivial}, c::PlanarTrivial) = 1
Base.isless(::PlanarTrivial, ::PlanarTrivial) = false

Base.one(::Type{PlanarTrivial}) = PlanarTrivial()
Base.conj(::PlanarTrivial) = PlanarTrivial()

FusionStyle(::Type{PlanarTrivial}) = UniqueFusion()
BraidingStyle(::Type{PlanarTrivial}) = NoBraiding()
Base.isreal(::Type{PlanarTrivial}) = true

Nsymbol(::Vararg{PlanarTrivial,3}) = 1
Fsymbol(::Vararg{PlanarTrivial,6}) = 1

(::PlanarTrivial, ::PlanarTrivial) = (PlanarTrivial(),)

# FibonacciAnyons
"""
struct FibonacciAnyon <: Sector
Expand Down
11 changes: 11 additions & 0 deletions src/spaces/planarspace.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
struct PlanarNumbers end # this is probably not a field?
const= PlanarNumbers()
Base.show(io::IO, ::PlanarNumbers) = print(io, "")

# convenience constructor
Base.:^(::PlanarNumbers, d::Int) = Vect[PlanarTrivial](PlanarTrivial() => d)

# convenience show
function Base.show(io::IO, V::GradedSpace{PlanarTrivial})
return print(io, isdual(V) ? "(ℙ^$(dim(V)))'" : "ℙ^$(dim(V))")
end
1 change: 1 addition & 0 deletions src/spaces/vectorspaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ include("generalspace.jl")
# space with internal structure corresponding to the irreducible representations of
# a group, or more generally, the simple objects of a fusion category.
include("gradedspace.jl")
include("planarspace.jl")

# Specific realizations of CompositeSpace types
#-----------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/tensors/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ function LinearAlgebra.mul!(tC::AbstractTensorMap,
tA::AbstractTensorMap,
tB::AbstractTensorMap, α = true, β = false)
if !(codomain(tC) == codomain(tA) && domain(tC) == domain(tB) && domain(tA) == codomain(tB))
throw(SpaceMismatch())
throw(SpaceMismatch("$(space(tC))$(space(tA)) * $(space(tB))"))
end
for c in blocksectors(tC)
if hasblock(tA, c) # then also tB should have such a block
Expand Down
11 changes: 11 additions & 0 deletions src/tensors/tensoroperations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ function TO.tensorcontract_structure(pC::Index2Tuple{N₁,N₂},
return dom cod
end

function TO.checkcontractible(tA::AbstractTensorMap{S}, iA::Int, conjA::Symbol,
tB::AbstractTensorMap{S}, iB::Int, conjB::Symbol, label) where {S}
sA = TO.tensorstructure(tA, iA, conjA)'
sB = TO.tensorstructure(tB, iB, conjB)
sA == sB ||
throw(SpaceMismatch("incompatible spaces for $label: $sA$sB"))
return nothing
end

TO.tensorcost(t::AbstractTensorMap, i::Int) = dim(space(t, i))

#----------------
# IMPLEMENTATONS
#----------------
Expand Down
2 changes: 1 addition & 1 deletion src/tensors/vectorinterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function VectorInterface.add(ty::AbstractTensorMap, tx::AbstractTensorMap, α::O
return VectorInterface.add!(scale!(similar(ty, T), ty, β), tx, α)
end
function VectorInterface.add!(ty::AbstractTensorMap, tx::AbstractTensorMap, α::ONumber=_one, β::ONumber=_one)
space(ty) == space(tx) || throw(SpaceMismatch())
space(ty) == space(tx) || throw(SpaceMismatch("$(space(ty))$(space(tx))"))
for c in blocksectors(tx)
VectorInterface.add!(block(ty, c), block(tx, c), α, β)
end
Expand Down
133 changes: 133 additions & 0 deletions test/planar.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using TensorKit, TensorOperations, Test
using TensorKit: planaradd!, planartrace!, planarcontract!
using TensorKit: PlanarTrivial, ℙ

"""
force_planar(obj)
Replace an object with a planar equivalent -- i.e. one that disallows braiding.
"""
force_planar(V::ComplexSpace) = isdual(V) ? (ℙ^dim(V))' :^dim(V)
function force_planar(V::GradedSpace)
return GradedSpace((c PlanarTrivial() => dim(V, c) for c in sectors(V))..., isdual(V))
end
force_planar(V::ProductSpace) = mapreduce(force_planar, , V)
function force_planar(tsrc::TensorMap{ComplexSpace})
tdst = TensorMap(undef, eltype(tsrc),
force_planar(codomain(tsrc)) force_planar(domain(tsrc)))
copyto!(blocks(tdst)[PlanarTrivial()], blocks(tsrc)[Trivial()])
return tdst
end
function force_planar(tsrc::TensorMap{<:GradedSpace})
tdst = TensorMap(undef, eltype(tsrc),
force_planar(codomain(tsrc)) force_planar(domain(tsrc)))
for (c, b) in blocks(tsrc)
copyto!(blocks(tdst)[c PlanarTrivial()], b)
end
return tdst
end

@testset "planar methods" verbose = true begin
@testset "planaradd" begin
A = TensorMap(randn, ℂ^2 ^3 ^6 ^5 ^4)
C = TensorMap(randn, (ℂ^5)' (ℂ^6)' ^4 (ℂ^3)' (ℂ^2)')
A′ = force_planar(A)
C′ = force_planar(C)
pC = ((4, 3), (5, 2, 1))

@test force_planar(tensoradd!(C, pC, A, :N, true, true))
planaradd!(C′, pC, A′, true, true)
end

@testset "planartrace" begin
A = TensorMap(randn, ℂ^2 ^3 ^2 ^5 ^4)
C = TensorMap(randn, (ℂ^5)' ^3 ^4)
A′ = force_planar(A)
C′ = force_planar(C)
pA = ((1,), (3,))
pC = ((4, 2), (5,))

@test force_planar(tensortrace!(C, pC, A, pA, :N, true, true))
planartrace!(C′, pC, A′, pA, true, true)
end

@testset "planarcontract" begin
A = TensorMap(randn, ℂ^2 ^3 ^2 ^5 ^4)
B = TensorMap(randn, ℂ^2 ^4 ^4 ^3)
C = TensorMap(randn, (ℂ^5)' (ℂ^2)' ^2 (ℂ^2)' ^4)

A′ = force_planar(A)
B′ = force_planar(B)
C′ = force_planar(C)

pA = ((1, 3, 4), (5, 2))
pB = ((2, 4), (1, 3))
pC = ((3, 2, 1), (4, 5))

@test force_planar(tensorcontract!(C, pC, A, pA, :N, B, pB, :N, true, true))
planarcontract!(C′, pC, A′, pA, B′, pB, true, true)
end
end

@testset "@planar" verbose=true begin
T = ComplexF64
@testset "MPS networks" begin
P =^2
Vmps =^12
Vmpo =^4

# ∂AC
# -------
x = TensorMap(randn, T, Vmps P Vmps)
O = TensorMap(randn, T, Vmpo P P Vmpo)
GL = TensorMap(randn, T, Vmps Vmpo' Vmps)
GR = TensorMap(randn, T, Vmps Vmpo Vmps)

x′ = force_planar(x)
O′ = force_planar(O)
GL′ = force_planar(GL)
GR′ = force_planar(GR)

@tensor y[-1 -2; -3] := GL[-1 2; 1] * x[1 3; 4] * O[2 -2; 3 5] * GR[4 5; -3]
@planar y′[-1 -2; -3] := GL′[-1 2; 1] * x′[1 3; 4] * O′[2 -2; 3 5] * GR′[4 5; -3]
@test force_planar(y) y′

# ∂AC2
# -------
x2 = TensorMap(randn, T, Vmps P Vmps P')
x2′ = force_planar(x2)
@tensor contractcheck=true y2[-1 -2; -3 -4] := GL[-1 7; 6] * x2[6 5; 1 3] * O[7 -2; 5 4] * O[4 -4; 3 2] * GR[1 2; -3]
@planar y2′[-1 -2; -3 -4] := GL′[-1 7; 6] * x2′[6 5; 1 3] * O′[7 -2; 5 4] * O′[4 -4; 3 2] * GR′[1 2; -3]
@test force_planar(y2) y2′
end

@testset "MERA networks" begin
Vmera =^2

u = TensorMap(randn, T, Vmera Vmera Vmera Vmera)
w = TensorMap(randn, T, Vmera Vmera Vmera)
ρ = TensorMap(randn, T, Vmera Vmera Vmera Vmera Vmera Vmera)
h = TensorMap(randn, T, Vmera Vmera Vmera Vmera Vmera Vmera)

u′ = force_planar(u)
w′ = force_planar(w)
ρ′ = force_planar(ρ)
h′ = force_planar(h)

@tensor begin
C = (((((((h[9 3 4; 5 1 2] * u[1 2; 7 12]) * conj(u[3 4; 11 13])) *
(u[8 5; 15 6] * w[6 7; 19])) *
(conj(u[8 9; 17 10]) * conj(w[10 11; 22]))) *
((w[12 14; 20] * conj(w[13 14; 23])) * ρ[18 19 20; 21 22 23])) *
w[16 15; 18]) * conj(w[16 17; 21]))
end
@planar begin
C′ = (((((((h′[9 3 4; 5 1 2] * u′[1 2; 7 12]) * conj(u′[3 4; 11 13])) *
(u′[8 5; 15 6] * w′[6 7; 19])) *
(conj(u′[8 9; 17 10]) * conj(w′[10 11; 22]))) *
((w′[12 14; 20] * conj(w′[13 14; 23])) * ρ′[18 19 20; 21 22 23])) *
w′[16 15; 18]) * conj(w′[16 17; 21]))
end
@test C C′
end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ include("sectors.jl")
include("fusiontrees.jl")
include("spaces.jl")
include("tensors.jl")
include("planar.jl")
Tf = time()
printstyled("Finished all tests in ",
string(round((Tf - Ti) / 60; sigdigits=3)),
Expand Down

0 comments on commit 951d341

Please sign in to comment.