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

Import Multipartition functionality from JuLie #4746

Merged
merged 48 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
9606ce6
Initial code from JuLie
mjrodgers Mar 20, 2025
6abec3f
No export because part of `src`
mjrodgers Mar 20, 2025
6f6a1ee
Put type definition where it belongs
mjrodgers Mar 20, 2025
80a3163
Fix type definition
mjrodgers Mar 20, 2025
f14021d
Fix Oscar compatibility
mjrodgers Mar 20, 2025
983b91d
`Vector` not `Array`
mjrodgers Mar 20, 2025
0ecec77
again `Vector` not `Array`
mjrodgers Mar 20, 2025
05b2871
set to 2 space indent, no tabs
mjrodgers Mar 20, 2025
252fb8e
from Review
mjrodgers Mar 21, 2025
1ab0cd8
type fix
mjrodgers Mar 21, 2025
4769f5f
add lowercase constructor
mjrodgers Mar 21, 2025
ebea4c1
Tests for both `Int`, `ZZRingElem`
mjrodgers Mar 21, 2025
bd6221b
add to `exports`
mjrodgers Mar 26, 2025
ec306ed
Export `Multipartition` type
mjrodgers Mar 27, 2025
e834620
fix deprecated `num_partitions` call
mjrodgers Mar 27, 2025
c7a6620
doctest fix
mjrodgers Mar 27, 2025
e910ed7
Fix copyright line
mjrodgers Mar 27, 2025
6a377d4
Update src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 27, 2025
b984af5
reorganize tests
mjrodgers Mar 27, 2025
2329bbb
better test names
mjrodgers Mar 27, 2025
18463a5
test organization
mjrodgers Mar 27, 2025
f2c1f7c
fix typo in doctest
mjrodgers Mar 27, 2025
1ce301b
fix another way
mjrodgers Mar 27, 2025
086fcde
fix `ZZRingElem` used for index
mjrodgers Mar 27, 2025
74dd089
fix `ZZ` for index x 6
mjrodgers Mar 27, 2025
68c9d97
Fix arg types for `number_of_multipartitions`
mjrodgers Mar 27, 2025
5265721
Put citation in proper format.
mjrodgers Mar 27, 2025
e87b426
missing comma in citation
mjrodgers Mar 27, 2025
1768d5e
fix bib
mjrodgers Mar 27, 2025
56b28e4
Update src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 28, 2025
6eaca86
Update src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 28, 2025
c27ab68
Update test/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 28, 2025
8df8e2d
Update test/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 28, 2025
1e2b98b
Update src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 28, 2025
4f79617
adjust ref to have `journal = unpublished`
mjrodgers Mar 31, 2025
c393a30
Fix issue with reducing empty array
mjrodgers Mar 31, 2025
e61fa14
no unicode in docstrings
mjrodgers Mar 31, 2025
e5023dc
No unicode in docstrings
mjrodgers Mar 31, 2025
3f1abc1
Add documentation
mjrodgers Mar 31, 2025
4aabd02
Update src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Mar 31, 2025
5bfa9f0
Allow `multipartitions(0,0)`
mjrodgers Mar 31, 2025
3b8cf31
attempt fix for giving an empty list to `multipartitions`
mjrodgers Mar 31, 2025
cd6bda6
fix typo...
mjrodgers Mar 31, 2025
10e381f
Clarify that partitions are given by weakly descending sequences.
mjrodgers Mar 31, 2025
c69b1d1
Fix citation
mjrodgers Mar 31, 2025
c00e546
return (phony) iterator to match API of `Partition`
mjrodgers Mar 31, 2025
1a30b62
Update src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
mjrodgers Apr 2, 2025
9fc395a
Update docs/doc.main
mjrodgers Apr 9, 2025
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
7 changes: 7 additions & 0 deletions docs/oscar_references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,13 @@ @Article{Cor21
doi = {10.1007/s00029-021-00679-6}
}

@Article{Cra06,
author = {Craven, D.},
title = {The number of $t$-cores of size $n$},
year = {2006},
url = {http://web.mat.bham.ac.uk/D.A.Craven/docs/papers/tcores0608.pdf}
}

@Book{Cut04,
author = {Cutkosky, Steven Dale},
title = {Resolution of singularities},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
include("types.jl")
include("partitions.jl")
include("multipartitions.jl")
include("schur_polynomials.jl")
include("tableaux.jl")
include("weak_compositions.jl")
Expand Down
166 changes: 166 additions & 0 deletions src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
################################################################################
# Multipartitions.
#
# Copyright (C) 2020 Ulrich Thiel, ulthiel.com/math
#
# Originally taken from the JuLie [repository](https://github.com/ulthiel/JuLie)
# by Ulrich Thiel and OSCAR-ified by Morgan Rodgers.
################################################################################




"""
multipartition(mp::Vector{Partition{T}}) where T <: IntegerUnion
multipartition(mp::Vector{Vector{T}}) where T <: IntegerUnion

Return the multipartition given by the vector `mp` of integer sequences `mp`
(which are interpreted as integer partitions) as an object of type
`Multipartition{T}`.

The element type `T` may be optionally specified, see also the examples below.

# Examples
```jldoctest
julia> P = multipartition([[2,1], [], [3,2,1]])
Partition{Int64}[[2, 1], [], [3, 2, 1]]
julia> sum(P)
9
julia> P[2]
Empty partition
julia> P = multipartition(Vector{Int8}[[2,1], [], [3,2,1]])
Partition{Int8}[[2, 1], [], [3, 2, 1]]
```

# References
1. Wikipedia, [Multipartition](https://en.wikipedia.org/wiki/Multipartition)
"""
function multipartition(mp::Vector{Partition{T}}) where T <: IntegerUnion
return Multipartition(mp)
end

function multipartition(mp::Vector{Vector{T}}) where T <: IntegerUnion
return Multipartition([partition(p) for p in mp])
end

# This is only called when the empty array is part of mp (because then it's
# "Any" type and not of Integer type).
function multipartition(mp::Vector{Vector{Any}})
return Multipartition([partition(p) for p in mp])
end

function Base.show(io::IO, ::MIME"text/plain", MP::Multipartition)
print(io, MP.mp)
end

function Base.size(MP::Multipartition)
return size(MP.mp)
end

function Base.length(MP::Multipartition)
return length(MP.mp)
end

function Base.getindex(MP::Multipartition, i::Int)
return getindex(MP.mp,i)
end


"""
sum(P::Multipartition{T}) where T<:IntegerUnion

If `P` is a multipartition of the integer n, this function returns n.
"""
function Base.sum(MP::Multipartition{T}) where T<:IntegerUnion
return sum(sum, MP.mp)
end


"""
multipartitions(n::T, r::IntegerUnion) where T<:IntegerUnion

A list of all `r`-component multipartitions of `n`, as elements of type Multipartitoon{T}.
The algorithm is recursive and based on [`partitions(::IntegerUnion)`](@ref).

# Example
```jldoctest
julia> multipartitions(2,2)
5-element Vector{Multipartition{Int64}}:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this perhaps like this?

Suggested change
5-element Vector{Multipartition{Int64}}:
5-element Vector{Partition{Int64}}:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But CI test pass... It seems I am misunderstanding something... huh

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it seems like this should be Vector{Multipartition}, this definitely passes CI but that doesn't mean that it's what we want... I'm looking at it now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, I understand the confusion. multipartitions returns ALL the multipartitions of n into r parts, so we get a Vector{Multipartition}. While each individual Multipartion looks like a Vector{Partition}. So this is all correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahah I get it now:

julia> foo = collect(MP)
5-element Vector{Multipartition{Int64}}:
 Partition{Int64}[[], [2]]
 Partition{Int64}[[], [1, 1]]
 Partition{Int64}[[1], [1]]
 Partition{Int64}[[2], []]
 Partition{Int64}[[1, 1], []]

julia> typeof(foo)
Vector{Multipartition{Int64}} (alias for Array{Multipartition{Int64}, 1})

julia> foo[1]
Partition{Int64}[[], [2]]

julia> typeof(foo[1])
Multipartition{Int64}

So my confusion is that Multipartition is printed as a Vector{Partition}. Which makes some sense, but at least for me it would be easier to understand what is going on if there was a custom show` method...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do this but I'm not sure what it should look like. We have the same issue with Partition printing as Vector{Int}:

julia> P = partition(6, 4, 4, 2)
[6, 4, 4, 2]

Partition{Int64}[[], [2]]
Partition{Int64}[[], [1, 1]]
Partition{Int64}[[1], [1]]
Partition{Int64}[[2], []]
Partition{Int64}[[1, 1], []]
```
"""
function multipartitions(n::T, r::IntegerUnion) where T<:IntegerUnion
#Argument checking
@req n >= 0 "n >= 0 required"
@req r >= 1 "r >= 1 required"

#This will be the list of multipartitions
MP = Multipartition{T}[]

#We will go through all compositions of n into r parts, and for each such #composition, we collect all the partitions for each of the components of
#the composition.
#We create the compositions here in place for efficiency.

#recursively produces all Integer Vectors p of length r such that the sum of all the Elements equals n. Then calls recMultipartitions!
function recP!(p::Vector{T}, i::T, n::T) #where T<:IntegerUnion
if i==length(p) || n==0
p[Int(i)] = n
recMultipartitions!(fill(Partition(T[]),r), p, T(1))
else
for j=0:n
p[Int(i)] = T(j)
recP!(copy(p), T(i+1), T(n-j))
end
end
end

#recursively produces all multipartitions such that the i-th partition sums up to p[i]
function recMultipartitions!(mp::Vector{Partition{T}}, p::Vector{T}, i::T) #where T<:IntegerUnion
if i == length(p)
for q in partitions(p[Int(i)])
mp[Int(i)] = q
push!(MP, Multipartition{T}(copy(mp)))
end
else
for q in partitions(p[Int(i)])
mp[Int(i)] = q
recMultipartitions!(copy(mp), p, T(i+1))
end
end
end

recP!(zeros(T,r), T(1), n)
return MP
end


@doc raw"""
number_of_multipartitions(n::IntegerUnion, k::IntegerUnion)

The number of multipartitions of ``n`` into ``k`` parts is equal to
```math
\sum_{a=1}^k {k \choose a} \sum_{λ} p(λ₁) p(λ₂) ⋯ p(λ_a) \;,
```
where the second sum is over all [compositions](@ref Compositions) ``λ`` of ``n`` into ``a`` parts. I found this formula in the Proof of Lemma 2.4 in [Cra06](@cite).
"""
function number_of_multipartitions(n::IntegerUnion, k::IntegerUnion)

# Special cases
n == 0 && return ZZ(k)

z = ZZ(0)
for a in 1:k
w = ZZ(0)
for lambda in compositions(n,a)
w += prod([number_of_partitions(lambda[i]) for i in 1:length(lambda)])
end
z += binomial(k,a)*w
end

return z

end
19 changes: 19 additions & 0 deletions src/Combinatorics/EnumerativeCombinatorics/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,25 @@ struct PartitionsFixedValues{T<:IntegerUnion}
end
end

################################################################################
#
# Multipartition
#
################################################################################

@doc raw"""
Multipartition{T<:IntegerUnion} <: AbstractVector{Partition{T}}

Multipartitions are generalizations of partitions. An r-component **multipartition** of an integer n is an r-tuple of partitions λ¹, λ², …, λʳ where each λⁱ is a partition of some integer nᵢ ≥ 0 and the nᵢ sum to n.

Multipartitions are implemented as a subtype of 1-dimensional arrays of partitions. You can use smaller integer types to increase performance.

See [`multipartition`](@ref) for the user-facing constructor and an example.
"""
struct Multipartition{T<:IntegerUnion} <: AbstractVector{Partition{T}}
mp::Vector{Partition{T}}
end

################################################################################
#
# Young Tableaux
Expand Down
4 changes: 4 additions & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export ModuleFPElem
export ModuleFPHom
export ModuleOrdering
export MonomialOrdering
export Multipartition
export Nemo
export NormalToricVariety
export OO
Expand Down Expand Up @@ -1170,6 +1171,8 @@ export mul!
export multi_hilbert_function
export multi_hilbert_series
export multi_hilbert_series_reduced
export multipartition
export multipartitions
export multiplication_induced_morphism
export multiplication_morphism
export multiplicative_jordan_decomposition
Expand Down Expand Up @@ -1241,6 +1244,7 @@ export number_of_factors
export number_of_generators
export number_of_groups_with_class_number, has_number_of_groups_with_class_number
export number_of_moved_points, has_number_of_moved_points, set_number_of_moved_points
export number_of_multipartitions
export number_of_partitions
export number_of_patches
export number_of_perfect_groups, has_number_of_perfect_groups
Expand Down
22 changes: 22 additions & 0 deletions test/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@testset "Multipartitions for integer type $T" for T in [Int, ZZRingElem]
#constructors
@test multipartition([T[3,2], T[1]]) == multipartition([Partition(T[3,2]), Partition(T[1])])
@test multipartition([T[3,2], T[]]) == multipartition([Partition(T[3,2]),Partition(T[])])

# multi-partitions
@testset "multipartitions($n, $r)" for n in 0:10, r in 1:5
MP = multipartitions(T(n),r)

@test MP == unique(MP)
@test length(MP) == 0 || unique([ length(mp) for mp in MP ]) == [r]
for mp in MP
@test sum(mp) == n
end
end

#counting
@testset "Counting multipartitions($n, $r)" for n in 0:5, r in 1:n+1
@test length(multipartitions(T(n),r)) == number_of_multipartitions(T(n),r)
end

end
Loading