Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some combinatorics #3860

Merged
merged 7 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Schur polynomials

Given a partition $\lambda$ of $n$, the **Schur polynomial** is defined to be
Given a partition $\lambda$ with $n$ parts, the **Schur polynomial** is defined to be
the polynomial

$$s_\lambda := \sum x_1^{m_1}\dots x_n^{m_n}$$
Expand Down
25 changes: 11 additions & 14 deletions src/Combinatorics/EnumerativeCombinatorics/partitions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,9 @@ function Base.iterate(P::Partitions{T}) where T
return partition(T[1], check=false), (T[1], 1, 0)
end

d = fill( T(1), n )
d = fill(T(1), Int(n))
d[1] = n
return partition(d[1:1], check=false), (d, 1, 1)

end

@inline function Base.iterate(P::Partitions{T}, state::Tuple{Vector{T}, Int, Int}) where T
Expand Down Expand Up @@ -381,7 +380,7 @@ function Base.iterate(P::PartitionsFixedNumParts{T}) where T
only_distinct_parts = P.distinct_parts

if n == 0 && k == 0
return partition(T[], check=false), (T[], T[], 0, 0, 1, false)
return partition(T[], check=false), (T[], T[], T(0), T(0), 1, false)
end

# This iterator should be empty
Expand All @@ -391,17 +390,17 @@ function Base.iterate(P::PartitionsFixedNumParts{T}) where T

if n == k && lb == 1
only_distinct_parts && k > 1 && return nothing
return partition(T[1 for i in 1:n], check=false), (T[], T[], 0, 0, 1, false)
return partition(T[1 for i in 1:n], check=false), (T[], T[], T(0), T(0), 1, false)
end

if k == 1 && lb <= n <= ub
return partition(T[n], check=false), (T[], T[], 0, 0, 1, false)
return partition(T[n], check=false), (T[], T[], T(0), T(0), 1, false)
end

x = zeros(T,k)
y = zeros(T,k)
jj = only_distinct_parts*k*(k-1)
N = n - k*lb - div(jj,2)
N = T(n - k*lb - div(jj,2))
L2 = ub-lb
0 <= N <= k*L2 - jj || return nothing

Expand All @@ -410,7 +409,7 @@ function Base.iterate(P::PartitionsFixedNumParts{T}) where T
end

i = 1
L2 = L2 - only_distinct_parts*(k-1)
L2 = L2 - only_distinct_parts*T(k-1)

while N > L2
N -= L2
Expand All @@ -421,15 +420,15 @@ function Base.iterate(P::PartitionsFixedNumParts{T}) where T
return partition(x[1:k], check = false), (x, y, N, L2, i, true)
end

@inline function Base.iterate(P::PartitionsFixedNumParts{T}, state::Tuple{Vector{T}, Vector{T}, T, IntegerUnion, Int, Bool}) where T
@inline function Base.iterate(P::PartitionsFixedNumParts{T}, state::Tuple{Vector{T}, Vector{T}, T, T, Int, Bool}) where T
k = P.k
x, y, N, L2, i, flag = state

N == 0 && return nothing

if flag
if i < k && N > 1
N = 1
N = T(1)
x[i] = x[i] - 1
i += 1
x[i] = y[i] + 1
Expand All @@ -442,12 +441,11 @@ end
flag = false
end
end

if !flag
lcycle = false
for j in i - 1:-1:1
L2 = x[j] - y[j] - 1
N = N + 1
L2 = x[j] - y[j] - T(1)
N = N + T(1)
if N <= (k-j)*L2
x[j] = y[j] + L2
lcycle = true
Expand All @@ -457,7 +455,6 @@ end
x[i] = y[i]
i = j
end

lcycle || return nothing
while N > L2
N -= L2
Expand Down Expand Up @@ -769,7 +766,7 @@ end
x[i] = m
i -= 1
i == 0 && break # inner while loop
r = ii[i]
r = Int(ii[i])
N = N + x[i] - m
m = y[i]
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function schur_polynomial_cbf(R::ZZMPolyRing, lambda::Partition{T}, n::Int = len
end

#calculate sub_dets[2:n] using Laplace extension
exp = zeros(Int, n)
exp = zeros(Int, ngens(R))
for i = 2:n
for (columnview, ) in sub_dets[i]
d = R() #the alternating sum of minors
Expand All @@ -134,8 +134,11 @@ function schur_polynomial_cbf(R::ZZMPolyRing, lambda::Partition{T}, n::Int = len

#multiply by the factorized term
factor = MPolyBuildCtx(R)
exp = zeros(Int, n)
exp[columnview] .= exp_incr[i]
exp = zeros(Int, ngens(R))
for j in 1:n
columnview[j] || continue
exp[j] = exp_incr[i]
end
push_term!(factor, one(ZZ), exp)
sub_dets[i][columnview] = mul!(d, d, finish(factor))
end
Expand Down
5 changes: 2 additions & 3 deletions src/Combinatorics/EnumerativeCombinatorics/tableaux.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@
data(tab::YoungTableau) = tab.t

function Base.show(io::IO, tab::YoungTableau)
print(io, "Young tableau")
# TODO: is there meaningful information to add in one-line mode?
print(io, data(tab))

Check warning on line 61 in src/Combinatorics/EnumerativeCombinatorics/tableaux.jl

View check run for this annotation

Codecov / codecov/patch

src/Combinatorics/EnumerativeCombinatorics/tableaux.jl#L61

Added line #L61 was not covered by tests
end

function Base.show(io::IO, ::MIME"text/plain", tab::YoungTableau)
Expand Down Expand Up @@ -591,7 +590,7 @@
numbs = falses(n)
for i = 1:length(s)
for j = 1:s[i]
if tab[i][j] > n
if tab[i][j] < 1 || tab[i][j] > n
return false
end
numbs[tab[i][j]] = true
Expand Down
6 changes: 3 additions & 3 deletions src/Combinatorics/EnumerativeCombinatorics/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ struct CompositionsFixedNumParts{T<:IntegerUnion}
if k > n
# 1 does not have any weak compositions into 0 parts, so this will
# produce an empty iterator
nk = 1
nk = T(1)
kk = 0
else
nk = n - k
nk = n - T(k)
kk = k
end
return new{T}(n, k, weak_compositions(nk, kk))
Expand Down Expand Up @@ -165,7 +165,7 @@ struct PartitionsFixedNumParts{T<:IntegerUnion}
if lb == 0
lb = 1
end
return new{T}(n, convert(T, k), T(lb), T(ub), only_distinct_parts)
return new{T}(n, Int(k), T(lb), T(ub), only_distinct_parts)
end

end
Expand Down
33 changes: 20 additions & 13 deletions test/Combinatorics/EnumerativeCombinatorics/compositions.jl
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
@testset "compositions" begin
@testset "Compositions with integer type $T" for T in [Int, Int8, ZZRingElem]
# Check some stupid cases
@test number_of_compositions(0, 0) == 1
@test number_of_compositions(0, 1) == 0
@test number_of_compositions(1, 0) == 0
@test number_of_compositions(0) == 1
@test number_of_compositions(T(0), T(0)) == 1
@test number_of_compositions(T(0), T(1)) == 0
@test number_of_compositions(T(1), T(0)) == 0
@test number_of_compositions(T(0)) == 1

# First few number of compositions from https://oeis.org/A011782
nums = [1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592]

# Check if number_of_compositions is correct in these examples
@test [number_of_compositions(n) for n in 0:length(nums) - 1] == nums
@test [number_of_compositions(T(n)) for n in 0:length(nums) - 1] == nums

# Complete check of compositions for small cases
for n in 0:5
# We'll piece together all compositions of n by the compositions
# of n into k parts for 0 <= k <= n
allcomps = []
for k in 0:n
C = collect(compositions(n, k))
@test length(C) == number_of_compositions(n, k)
C = @inferred collect(compositions(T(n), T(k)))
@test C isa Vector{Oscar.Composition{T}}
@test length(C) == number_of_compositions(T(n), T(k))

# Check if each composition consists of k parts and sums up to n
for c in C
Expand All @@ -37,19 +38,25 @@
@test allcomps == unique(allcomps)

# Number of compositions needs to be correct
@test length(allcomps) == number_of_compositions(n)
@test length(allcomps) == number_of_compositions(T(n))

# Finally, check compositions(n) function
allcomps2 = collect(compositions(n))
allcomps2 = @inferred collect(compositions(T(n)))
@test allcomps2 isa Vector{Oscar.Composition{T}}
@test allcomps2 == unique(allcomps2)
@test Set(allcomps) == Set(allcomps2)
end

# Test the case k > n
C = @inferred collect(compositions(T(2), T(3)))
@test C isa Vector{Oscar.Composition{T}}
@test isempty(C)
end

@testset "Ascending compositions" begin
@testset "Ascending compositions with integer type $T" for T in [Int, Int8, ZZRingElem]
for n in 0:20
C = collect(ascending_compositions(n))
@test length(C) == number_of_partitions(n)
C = @inferred collect(ascending_compositions(T(n)))
@test length(C) == number_of_partitions(T(n))
@test C == unique(C)
for lambda in C
@test sum(lambda) == n
Expand Down
Loading
Loading