From 27af0e9f215110dba6291129c5cb708b06fe5ce5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 2 Mar 2026 18:24:53 +0100 Subject: [PATCH 01/10] edit `smallset` to sample --- Project.toml | 3 ++- src/timereversed.jl | 9 +++++++-- test/testsuite.jl | 12 +++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index 3503d991..24069691 100644 --- a/Project.toml +++ b/Project.toml @@ -27,9 +27,10 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" +StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a" [targets] -test = ["Aqua", "JET", "Test", "TestExtras", "TensorOperations", "Random", "Reexport"] +test = ["Aqua", "JET", "Test", "TestExtras", "TensorOperations", "Random", "Reexport", "StatsBase"] diff --git a/src/timereversed.jl b/src/timereversed.jl index 7b70d8c4..9debce81 100644 --- a/src/timereversed.jl +++ b/src/timereversed.jl @@ -51,10 +51,15 @@ dual(c::TimeReversed{I}) where {I <: Sector} = TimeReversed{I}(dual(c.a)) function ⊗(c1::TimeReversed{I}, c2::TimeReversed{I}) where {I <: Sector} return SectorSet{TimeReversed{I}}(TimeReversed{I}, c1.a ⊗ c2.a) end -function Base.IteratorSize(::Type{SectorValues{TimeReversed{I}}}) where {I <: Sector} + +# capture product sectors as well +function Base.IteratorSize(::Type{SectorValues{TimeReversed{I}}}) where {I} return Base.IteratorSize(values(I)) end -function Base.length(::SectorValues{TimeReversed{I}}) where {I <: Sector} +function Base.size(::SectorValues{TimeReversed{I}}) where {I} + return size(values(I)) +end +function Base.length(::SectorValues{TimeReversed{I}}) where {I} return length(values(I)) end function Base.getindex(::SectorValues{TimeReversed{I}}, i::Int) where {I <: Sector} diff --git a/test/testsuite.jl b/test/testsuite.jl index 71a07df3..30f350f6 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -31,6 +31,7 @@ using TestExtras using TensorKitSectors using TensorKitSectors: type_repr using Random +using StatsBase using Base.Iterators: take, product const tests = Dict() @@ -69,7 +70,16 @@ function test_sector(I::Type) end end -smallset(::Type{I}) where {I <: Sector} = take(values(I), 5) +function StatsBase.sample(::SectorValues{I}, size::Int) where {I <: Sector} + Base.IteratorSize(values(I)) === Base.IsInfinite() && + throw(ArgumentError("Cannot take random sample of infinite sector values.")) + return sample(collect(values(I)), size; replace = false) # unique sampling +end +function smallset(::Type{I}, size::Int = 5) where {I <: Sector} + vals = values(I) + Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) + return sample(vals, min(size, length(vals))) +end function smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1, I2} iter = product(smallset(I1), smallset(I2)) s = collect(i ⊠ j for (i, j) in iter if dim(i) * dim(j) <= 6) From 2a96e1ebb3c308f75231fd18d61373bcccf7abf9 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 3 Mar 2026 09:21:55 +0100 Subject: [PATCH 02/10] add compat --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 24069691..205a58a3 100644 --- a/Project.toml +++ b/Project.toml @@ -17,6 +17,7 @@ julia = "1.10" LinearAlgebra = "1" Random = "1" Reexport = "1" +StatsBase = "0.34" TensorOperations = "5" Test = "1" TestExtras = "0.3.2" From 5648c7b89e71d5ef24bde160e05c690a568e8114 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 3 Mar 2026 17:24:02 +0100 Subject: [PATCH 03/10] sample without relying on StatsBase --- Project.toml | 4 +--- test/testsuite.jl | 13 ++++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Project.toml b/Project.toml index 205a58a3..3503d991 100644 --- a/Project.toml +++ b/Project.toml @@ -17,7 +17,6 @@ julia = "1.10" LinearAlgebra = "1" Random = "1" Reexport = "1" -StatsBase = "0.34" TensorOperations = "5" Test = "1" TestExtras = "0.3.2" @@ -28,10 +27,9 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" -StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a" [targets] -test = ["Aqua", "JET", "Test", "TestExtras", "TensorOperations", "Random", "Reexport", "StatsBase"] +test = ["Aqua", "JET", "Test", "TestExtras", "TensorOperations", "Random", "Reexport"] diff --git a/test/testsuite.jl b/test/testsuite.jl index dd0ebcc2..fe30dae9 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -31,7 +31,6 @@ using TestExtras using TensorKitSectors using TensorKitSectors: type_repr using Random -using StatsBase using Base.Iterators: take, product const tests = Dict() @@ -70,15 +69,15 @@ function test_sector(I::Type) end end -function StatsBase.sample(::SectorValues{I}, size::Int) where {I <: Sector} - Base.IteratorSize(values(I)) === Base.IsInfinite() && - throw(ArgumentError("Cannot take random sample of infinite sector values.")) - return sample(collect(values(I)), size; replace = false) # unique sampling -end function smallset(::Type{I}, size::Int = 5) where {I <: Sector} vals = values(I) Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) - return sample(vals, min(size, length(vals))) + L = length(vals) + set = Random.randsubseq(collect(vals), min(size, L) / L) # contains between size and length(values(I)) sectors + while length(set) < min(size, L) + Random.randsubseq!(set, collect(vals), min(size, L) / L) + end + return set # returns all sectors if L < size end function smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1, I2} iter = product(smallset(I1), smallset(I2)) From de05875314a5a0697adba959f264727efb4bdc6d Mon Sep 17 00:00:00 2001 From: Boris De Vos <143942306+borisdevos@users.noreply.github.com> Date: Wed, 4 Mar 2026 08:32:50 +0100 Subject: [PATCH 04/10] Update test/testsuite.jl Co-authored-by: Lukas Devos --- test/testsuite.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/testsuite.jl b/test/testsuite.jl index fe30dae9..f1257127 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -74,9 +74,6 @@ function smallset(::Type{I}, size::Int = 5) where {I <: Sector} Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) L = length(vals) set = Random.randsubseq(collect(vals), min(size, L) / L) # contains between size and length(values(I)) sectors - while length(set) < min(size, L) - Random.randsubseq!(set, collect(vals), min(size, L) / L) - end return set # returns all sectors if L < size end function smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1, I2} From cc5022c368330ef287dcfdbb55eb6b3656a16fe0 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 4 Mar 2026 10:11:28 +0100 Subject: [PATCH 05/10] prevent empty smallsets --- test/testsuite.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/testsuite.jl b/test/testsuite.jl index f1257127..29b9edc4 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -74,6 +74,9 @@ function smallset(::Type{I}, size::Int = 5) where {I <: Sector} Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) L = length(vals) set = Random.randsubseq(collect(vals), min(size, L) / L) # contains between size and length(values(I)) sectors + while isempty(set) + Random.randsubseq!(set, collect(vals), min(size, L) / L) + end return set # returns all sectors if L < size end function smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1, I2} From 388461056889f754d6e8e36bbd3408a302dd4c1c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 4 Mar 2026 14:07:54 +0100 Subject: [PATCH 06/10] refactor `randsubseq` and use for deligne products as well --- test/testsuite.jl | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/test/testsuite.jl b/test/testsuite.jl index 29b9edc4..95b183ac 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -69,25 +69,43 @@ function test_sector(I::Type) end end +function Random.randsubseq(v::SectorValues{I}, p::Float64) where {I <: Sector} + cvals = collect(v) + set = Random.randsubseq(cvals, p) # contains between size and length(values(I)) sectors + while isempty(set) + Random.randsubseq!(set, cvals, p) # sector types with many sectors sample with low probability + end + return set +end function smallset(::Type{I}, size::Int = 5) where {I <: Sector} vals = values(I) Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) L = length(vals) - set = Random.randsubseq(collect(vals), min(size, L) / L) # contains between size and length(values(I)) sectors - while isempty(set) - Random.randsubseq!(set, collect(vals), min(size, L) / L) - end - return set # returns all sectors if L < size + return Random.randsubseq(vals, min(size, L) / L) # returns all sectors if L < size end -function smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1, I2} +function smallset(I::Type{ProductSector{Tuple{I1, I2}}}, size::Int = 6) where {I1, I2} iter = product(smallset(I1), smallset(I2)) s = collect(i ⊠ j for (i, j) in iter if dim(i) * dim(j) <= 6) - return length(s) > 6 ? rand(s, 6) : s + if length(s) < 6 + return s + else + vals = values(I) + Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) + L = length(vals) + return Random.randsubseq(vals, min(size, L) / L) + end end -function smallset(::Type{ProductSector{Tuple{I1, I2, I3}}}) where {I1, I2, I3} +function smallset(I::Type{ProductSector{Tuple{I1, I2, I3}}}, size::Int = 6) where {I1, I2, I3} iter = product(smallset(I1), smallset(I2), smallset(I3)) s = collect(i ⊠ j ⊠ k for (i, j, k) in iter if dim(i) * dim(j) * dim(k) <= 6) - return length(s) > 6 ? rand(s, 6) : s + if length(s) < 6 + return s + else + vals = values(I) + Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) + L = length(vals) + return Random.randsubseq(vals, min(size, L) / L) + end end function randsector(::Type{I}) where {I <: Sector} From 2a15d92aa956fb85b4f3fb936476be867ccd678c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 4 Mar 2026 14:53:32 +0100 Subject: [PATCH 07/10] sample with fixed size --- test/testsuite.jl | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/test/testsuite.jl b/test/testsuite.jl index 95b183ac..4a1ed030 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -69,19 +69,12 @@ function test_sector(I::Type) end end -function Random.randsubseq(v::SectorValues{I}, p::Float64) where {I <: Sector} - cvals = collect(v) - set = Random.randsubseq(cvals, p) # contains between size and length(values(I)) sectors - while isempty(set) - Random.randsubseq!(set, cvals, p) # sector types with many sectors sample with low probability - end - return set -end function smallset(::Type{I}, size::Int = 5) where {I <: Sector} vals = values(I) Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) L = length(vals) - return Random.randsubseq(vals, min(size, L) / L) # returns all sectors if L < size + p = resize!(randperm(L), min(size, L)) # sampling with fixed size + return collect(vals)[p] end function smallset(I::Type{ProductSector{Tuple{I1, I2}}}, size::Int = 6) where {I1, I2} iter = product(smallset(I1), smallset(I2)) @@ -92,7 +85,8 @@ function smallset(I::Type{ProductSector{Tuple{I1, I2}}}, size::Int = 6) where {I vals = values(I) Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) L = length(vals) - return Random.randsubseq(vals, min(size, L) / L) + p = resize!(randperm(L), min(size, L)) + return collect(vals)[p] end end function smallset(I::Type{ProductSector{Tuple{I1, I2, I3}}}, size::Int = 6) where {I1, I2, I3} @@ -104,7 +98,8 @@ function smallset(I::Type{ProductSector{Tuple{I1, I2, I3}}}, size::Int = 6) wher vals = values(I) Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) L = length(vals) - return Random.randsubseq(vals, min(size, L) / L) + p = resize!(randperm(L), min(size, L)) + return collect(vals)[p] end end From 39d38cf40405472024122169bc696bb5ad4d78c6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Mar 2026 09:04:06 +0100 Subject: [PATCH 08/10] use `shuffle` and have it work for infinite sectors + product sectors --- test/testsuite.jl | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/test/testsuite.jl b/test/testsuite.jl index 4a1ed030..ffe2d145 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -69,38 +69,12 @@ function test_sector(I::Type) end end -function smallset(::Type{I}, size::Int = 5) where {I <: Sector} +function smallset(::Type{I}, size::Int = 5, maxdim::Real = 10) where {I <: Sector} vals = values(I) - Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) - L = length(vals) - p = resize!(randperm(L), min(size, L)) # sampling with fixed size - return collect(vals)[p] -end -function smallset(I::Type{ProductSector{Tuple{I1, I2}}}, size::Int = 6) where {I1, I2} - iter = product(smallset(I1), smallset(I2)) - s = collect(i ⊠ j for (i, j) in iter if dim(i) * dim(j) <= 6) - if length(s) < 6 - return s - else - vals = values(I) - Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) - L = length(vals) - p = resize!(randperm(L), min(size, L)) - return collect(vals)[p] - end -end -function smallset(I::Type{ProductSector{Tuple{I1, I2, I3}}}, size::Int = 6) where {I1, I2, I3} - iter = product(smallset(I1), smallset(I2), smallset(I3)) - s = collect(i ⊠ j ⊠ k for (i, j, k) in iter if dim(i) * dim(j) * dim(k) <= 6) - if length(s) < 6 - return s - else - vals = values(I) - Base.IteratorSize(vals) === Base.IsInfinite() && return take(vals, size) - L = length(vals) - p = resize!(randperm(L), min(size, L)) - return collect(vals)[p] - end + L = Base.IteratorSize(vals) === Base.IsInfinite() ? 10 * size : min(10 * size, length(vals)) + sectors = getindex.((vals,), 1:L) # include unit in simple-unit categories + sectors = shuffle!(filter!(s -> dim(s) < maxdim, sectors)) + return sectors[1:min(size, length(sectors))] end function randsector(::Type{I}) where {I <: Sector} From ccbdc97901831f4aac8031bffa4879231cd49720 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Mar 2026 15:31:15 +0100 Subject: [PATCH 09/10] code suggestions --- test/testsuite.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/testsuite.jl b/test/testsuite.jl index ffe2d145..ba024875 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -70,11 +70,9 @@ function test_sector(I::Type) end function smallset(::Type{I}, size::Int = 5, maxdim::Real = 10) where {I <: Sector} - vals = values(I) - L = Base.IteratorSize(vals) === Base.IsInfinite() ? 10 * size : min(10 * size, length(vals)) - sectors = getindex.((vals,), 1:L) # include unit in simple-unit categories + sectors = collect(Iterators.take(values(I), 10 * size)) # include unit in simple-unit categories sectors = shuffle!(filter!(s -> dim(s) < maxdim, sectors)) - return sectors[1:min(size, length(sectors))] + return resize!(sectors, min(size, length(sectors))) end function randsector(::Type{I}) where {I <: Sector} From 798ed4f45d48804d45d7d4e4991f4e28ebebbcd9 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Mar 2026 16:44:49 +0100 Subject: [PATCH 10/10] deal with comments about comments and remove comments with no comment --- src/timereversed.jl | 1 - test/testsuite.jl | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/timereversed.jl b/src/timereversed.jl index 9debce81..2796c771 100644 --- a/src/timereversed.jl +++ b/src/timereversed.jl @@ -52,7 +52,6 @@ function ⊗(c1::TimeReversed{I}, c2::TimeReversed{I}) where {I <: Sector} return SectorSet{TimeReversed{I}}(TimeReversed{I}, c1.a ⊗ c2.a) end -# capture product sectors as well function Base.IteratorSize(::Type{SectorValues{TimeReversed{I}}}) where {I} return Base.IteratorSize(values(I)) end diff --git a/test/testsuite.jl b/test/testsuite.jl index ba024875..fc225e66 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -70,7 +70,7 @@ function test_sector(I::Type) end function smallset(::Type{I}, size::Int = 5, maxdim::Real = 10) where {I <: Sector} - sectors = collect(Iterators.take(values(I), 10 * size)) # include unit in simple-unit categories + sectors = collect(Iterators.take(values(I), 10 * size)) sectors = shuffle!(filter!(s -> dim(s) < maxdim, sectors)) return resize!(sectors, min(size, length(sectors))) end