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

Make partitions and (semi)standard_tableaux return iterators #3365

Merged
merged 1 commit into from
Feb 16, 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
Expand Up @@ -75,7 +75,7 @@ one can also handle more general types of restrictions.
For example, there are precisely six ways for the second question in the exercise quoted
above:
```jldoctest
julia> partitions(100, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2])
julia> collect(partitions(100, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2]))
6-element Vector{Partition{Int64}}:
[50, 50]
[50, 20, 20, 10]
Expand Down
2 changes: 1 addition & 1 deletion experimental/LieAlgebras/src/Combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function multicombinations(n::Integer, k::Integer)
return sort(
map(
reverse ∘ Vector,
reduce(vcat, partitions(i, k, 1, n) for i in 0:(k * n); init=Vector{Int}[]),
reduce(vcat, collect(partitions(i, k, 1, n)) for i in 0:(k * n); init=Vector{Int}[]),
),
)
end
Expand Down
84 changes: 47 additions & 37 deletions src/Combinatorics/EnumerativeCombinatorics/partitions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,29 @@ end
@doc raw"""
partitions(n::IntegerUnion)

Return a list of all partitions of a non-negative integer `n`, produced in
lexicographically *descending* order.
Return an iterator over all partitions of a non-negative integer `n`, produced
in lexicographically *descending* order.
Using a smaller integer type for `n` (e.g. `Int8`) may increase performance.

The algorithm used is "Algorithm ZS1" by [ZS98](@cite). This algorithm is also
discussed in [Knu11](@cite), Algorithm P (page 392).

# Examples
```jldoctest
julia> partitions(4)
julia> p = partitions(4);

julia> first(p)
[4]

julia> collect(p)
5-element Vector{Partition{Int64}}:
[4]
[3, 1]
[2, 2]
[2, 1, 1]
[1, 1, 1, 1]

julia> partitions(Int8(4)) # using less memory
julia> collect(partitions(Int8(4))) # using less memory
5-element Vector{Partition{Int8}}:
Int8[4]
Int8[3, 1]
Expand All @@ -184,9 +189,9 @@ function partitions(n::T) where T <: IntegerUnion

# Some trivial cases
if n == 0
return Partition{T}[ partition(T[], check = false) ]
return (p for p in Partition{T}[ partition(T[], check = false) ])
elseif n == 1
return Partition{T}[ partition(T[1], check = false) ]
return (p for p in Partition{T}[ partition(T[1], check = false) ])
end

# Now, the algorithm starts
Expand Down Expand Up @@ -222,7 +227,7 @@ function partitions(n::T) where T <: IntegerUnion
end
push!(P, partition(d[1:k], check = false))
end
return P
return (p for p in P)
end

################################################################################
Expand Down Expand Up @@ -287,9 +292,10 @@ end
partitions(m::IntegerUnion, n::IntegerUnion; only_distinct_parts::Bool = false)
partitions(m::IntegerUnion, n::IntegerUnion, l1::IntegerUnion, l2::IntegerUnion; only_distinct_parts::Bool = false)

Return all partitions of a non-negative integer `m` into `n >= 0` parts.
Optionally, a lower bound `l1 >= 0` and an upper bound `l2` for the parts can be
supplied. In this case, the partitions are produced in *decreasing* order.
Return an iterator over all partitions of a non-negative integer `m` into
`n >= 0` parts. Optionally, a lower bound `l1 >= 0` and an upper bound `l2` for
the parts can be supplied. In this case, the partitions are produced in
*decreasing* order.

There are two choices for the parameter `only_distinct_parts`:
* `false`: no further restriction (*default*);
Expand All @@ -300,7 +306,7 @@ The implemented algorithm is "parta" in [RJ76](@cite).
# Examples
All partitions of 7 into 3 parts:
```jldoctest
julia> partitions(7, 3)
julia> collect(partitions(7, 3))
4-element Vector{Partition{Int64}}:
[5, 1, 1]
[4, 2, 1]
Expand All @@ -309,15 +315,15 @@ julia> partitions(7, 3)
```
All partitions of 7 into 3 parts where all parts are between 1 and 4:
```jldoctest
julia> partitions(7, 3, 1, 4)
julia> collect(partitions(7, 3, 1, 4))
3-element Vector{Partition{Int64}}:
[4, 2, 1]
[3, 3, 1]
[3, 2, 2]
```
Same as above but requiring all parts to be distinct:
```jldoctest
julia> partitions(7, 3, 1, 4; only_distinct_parts = true)
julia> collect(partitions(7, 3, 1, 4; only_distinct_parts = true))
1-element Vector{Partition{Int64}}:
[4, 2, 1]
```
Expand All @@ -339,15 +345,15 @@ function partitions(m::T, n::IntegerUnion, l1::IntegerUnion, l2::IntegerUnion; o

# Some trivial cases
if m == 0 && n == 0
return Partition{T}[ partition(T[], check = false) ]
return (p for p in Partition{T}[ partition(T[], check = false) ])
end

if n == 0 || n > m
return Partition{T}[]
return (p for p in Partition{T}[])
end

if l2 < l1
return Partition{T}[]
return (p for p in Partition{T}[])
end

# If l1 == 0 the algorithm parta will actually create lists containing the
Expand Down Expand Up @@ -411,7 +417,7 @@ function partitions(m::T, n::IntegerUnion, l1::IntegerUnion, l2::IntegerUnion; o
end
end

return P
return (p for p in P)
end

function partitions(m::T, n::IntegerUnion; only_distinct_parts::Bool = false) where T <: IntegerUnion
Expand All @@ -420,14 +426,14 @@ function partitions(m::T, n::IntegerUnion; only_distinct_parts::Bool = false) wh

# Special cases
if m == n
return [ partition(T[ 1 for i in 1:m], check = false) ]
return (p for p in [ partition(T[ 1 for i in 1:m], check = false) ])
elseif m < n || n == 0
return Partition{T}[]
return (p for p in Partition{T}[])
elseif n == 1
return [ partition(T[m], check = false) ]
return (p for p in [ partition(T[m], check = false) ])
end

return partitions(m, n, 1, m; only_distinct_parts = only_distinct_parts)
return (p for p in partitions(m, n, 1, m; only_distinct_parts = only_distinct_parts))
end

function partitions(m::T, n::IntegerUnion, v::Vector{T}, mu::Vector{S}) where {T <: IntegerUnion, S <: IntegerUnion}
Expand All @@ -451,15 +457,17 @@ function partitions(m::T, n::IntegerUnion, v::Vector{T}, mu::Vector{S}) where {T

# Special cases
if n == 0
# TODO: I don't understand this distinction here
# (it also makes the function tabe instable)
if m == 0
return [ Partition{T}[] ]
return (p for p in [ Partition{T}[] ])
else
return Partition{T}[]
return (p for p in Partition{T}[])
end
end

if isempty(mu)
return Partition{T}[]
return (p for p in Partition{T}[])
end

#This will be the list of all partitions found.
Expand Down Expand Up @@ -523,7 +531,7 @@ function partitions(m::T, n::IntegerUnion, v::Vector{T}, mu::Vector{S}) where {T

# This is a necessary condition for existence of a partition
if m < 0 || m > n * (lr - ll)
return P #goto b3
return (p for p in P) #goto b3
end

# The following is a condition for when only a single partition
Expand All @@ -534,7 +542,7 @@ function partitions(m::T, n::IntegerUnion, v::Vector{T}, mu::Vector{S}) where {T
# Noticed on Mar 23, 2023.
if m == 0 && x[1] != 0
push!(P, partition(copy(x), check = false))
return P
return (p for p in P)
end

# Now, the actual algorithm starts
Expand Down Expand Up @@ -625,7 +633,7 @@ function partitions(m::T, n::IntegerUnion, v::Vector{T}, mu::Vector{S}) where {T
end #if gotob2
end #while

return P
return (p for p in P)
end

function partitions(m::T, v::Vector{T}, mu::Vector{S}) where {T <: IntegerUnion, S <: IntegerUnion}
Expand All @@ -645,11 +653,12 @@ function partitions(m::T, v::Vector{T}, mu::Vector{S}) where {T <: IntegerUnion,
res = Partition{T}[]

if isempty(v)
return res
return (p for p in res)
end

if m == 0
return [ Partition{T}[] ]
# TODO: I don't understand this return (and it is type instable)
return (p for p in [ Partition{T}[] ])
end

# We will loop over the number of parts.
Expand Down Expand Up @@ -680,16 +689,16 @@ function partitions(m::T, v::Vector{T}, mu::Vector{S}) where {T <: IntegerUnion,
append!(res, partitions(m, n, v, mu))
end

return res
return (p for p in res)
end

@doc raw"""
partitions(m::T, v::Vector{T}) where T <: IntegerUnion
partitions(m::T, v::Vector{T}, mu::Vector{<:IntegerUnion}) where T <: IntegerUnion
partitions(m::T, n::IntegerUnion, v::Vector{T}, mu::Vector{<:IntegerUnion}) where T <: IntegerUnion

Return all partitions of a non-negative integer `m` where each part is an element
in the vector `v` of positive integers.
Return an iterator over all partitions of a non-negative integer `m` where each
part is an element in the vector `v` of positive integers.
It is assumed that the entries in `v` are strictly increasing.

If the optional vector `mu` is supplied, then each `v[i]` occurs a maximum of
Expand All @@ -710,7 +719,7 @@ julia> length(partitions(100, [1, 2, 5, 10, 20, 50]))
All partitions of 100 where the parts are from {1, 2, 5, 10, 20, 50} and each
part is allowed to occur at most twice:
```jldoctest
julia> partitions(100, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2])
julia> collect(partitions(100, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2]))
6-element Vector{Partition{Int64}}:
[50, 50]
[50, 20, 20, 10]
Expand All @@ -722,7 +731,7 @@ julia> partitions(100, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2])
The partitions of 100 into seven parts, where the parts are required to be
elements from {1, 2, 5, 10, 20, 50} and each part is allowed to occur at most twice.
```jldoctest
julia> partitions(100, 7, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2])
julia> collect(partitions(100, 7, [1, 2, 5, 10, 20, 50], [2, 2, 2, 2, 2, 2]))
1-element Vector{Partition{Int64}}:
[50, 20, 20, 5, 2, 2, 1]
```
Expand All @@ -735,11 +744,12 @@ function partitions(m::T, v::Vector{T}) where T <: IntegerUnion
res = Partition{T}[]

if isempty(v)
return res
return (p for p in res)
end

if m == 0
return [ Partition{T}[] ]
# TODO: I don't understand this return (and it is type instable)
return (p for p in [ Partition{T}[] ])
end

# We will loop over the number of parts.
Expand All @@ -755,7 +765,7 @@ function partitions(m::T, v::Vector{T}) where T <: IntegerUnion
append!(res, partitions(m, n, v, mu))
end

return res
return (p for p in res)
end

################################################################################
Expand Down
Loading
Loading