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

Open
wants to merge 47 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
47 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
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
1 change: 1 addition & 0 deletions docs/doc.main
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@
"Combinatorics/phylogenetic_trees.md",
"Enumerative combinatorics" => [
"Combinatorics/EnumerativeCombinatorics/partitions.md",
"Combinatorics/EnumerativeCombinatorics/multipartitions.md",
"Combinatorics/EnumerativeCombinatorics/tableaux.md",
"Combinatorics/EnumerativeCombinatorics/schur_polynomials.md",
"Combinatorics/EnumerativeCombinatorics/compositions.md",
Expand Down
21 changes: 21 additions & 0 deletions docs/oscar_references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,19 @@ @Article{AZ99
url = {https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=6eaea4b5c868c84295a0977ed9fce92d7c960a39}
}

@InCollection{And08,
author = {Andrews, George E.},
title = {A survey of multipartitions congruences and identities},
editor = {Alladi, Krishnaswarmi},
booktitle = {Surveys in Number Theory},
series = {Developments in Mathematics},
volume = {17},
publisher = {Springer New York},
pages = {1--19},
year = {2008},
doi = {10.1007/978-0-387-78510-3_1}
}

@Article{BBS02,
author = {Bayer, M. and Bruening, A. and Stewart, J.},
title = {A Combinatorial Study of Multiplexes and Ordinary Polytopes},
Expand Down Expand Up @@ -742,6 +755,14 @@ @Article{Cor21
doi = {10.1007/s00029-021-00679-6}
}

@Article{Cra06,
author = {Craven, D.},
title = {The number of $t$-cores of size $n$},
journal = {unpublished},
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
51 changes: 51 additions & 0 deletions docs/src/Combinatorics/EnumerativeCombinatorics/multipartitions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
```@meta
CurrentModule = Oscar
DocTestSetup = Oscar.doctestsetup()
```

# Multipartitions


Multipartitions are generalizations of partitions.
An $r$-component **multipartition** of an integer ``n``
is an $r$-tuple of partitions $\lambda = (\lambda_1, \lambda_2, \ldots, \lambda_r)$
where each $\lambda_i$ is a partition of some integer $n_i \geq 0$
and the $n_i$ sum to $n$.
For an overview of multipartitions, see [And08](@cite).

A multipartition can be encoded as a 1-dimensional array whose elements are partitions.
In OSCAR, we provide the parametric type `Multipartition{T}` which is a subtype of `AbstractVector{T}`,
where `T` can by any subtype of `IntegerUnion`.
By using smaller integer types when appropriate, this allows performance to be improved.

```@docs
multipartition
```
Because `Multipartition` is a subtype of `AbstractVector`, all functions that can be used for vectors (1-dimensional arrays) can be used for multipartitions as well.
```jldoctest
julia> MP = multipartition([[3, 2], [1, 1], [3, 1]])
Partition{Int64}[[3, 2], [1, 1], [3, 1]]

julia> length(MP)
3

julia> MP[1]
[3, 2]
```
However, usually, $|\lambda| := n$ is called the **size** of a multipartition $\lambda$.
In Julia, the function `size` for arrays already exists and returns the *dimension* of an array.
Instead, one can use the Julia function `sum` to get the sum of the parts.
```jldoctest
julia> MP = multipartition([[3, 2], [1, 1], [3, 1]])
Partition{Int64}[[3, 2], [1, 1], [3, 1]]

julia> sum(MP)
11
```

## Generating and counting

```@docs
multipartitions(::Oscar.IntegerUnion, ::Oscar.IntegerUnion)
number_of_multipartitions(::Oscar.IntegerUnion, ::Oscar.IntegerUnion)
```
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
177 changes: 177 additions & 0 deletions src/Combinatorics/EnumerativeCombinatorics/multipartitions.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
################################################################################
# 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}`.
Note that a partition must be given by a weakly descending integer sequence.

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]]
```
"""
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

# This is only called when mp is itself an empty array.
function multipartition(mp::Vector{Any})
return Multipartition(Vector{Partition{Int}}(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; init=zero(T))
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> MP = multipartitions(2,2);

julia> first(MP)
Partition{Int64}[[], [2]]

julia> collect(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 >= 0 "r >= 0 required"
@req n == 0 || r >= 1 "impossible with r == 0 and n >= 1"

#This will be the list of multipartitions
MP = Multipartition{T}[]
n == r == 0 && return MP

#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 (x for x in MP)
# 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_{\lambda} p(\lambda_1) p(\lambda_2) \cdots p(\lambda_a) \;,
```
where the second sum is over all [compositions](@ref Compositions) ``\lambda`` of ``n`` into ``a`` parts. This formula is due to [Cra06; Proof of Lemma 2.4](@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 = sum(lambda -> prod(number_of_partitions, lambda), compositions(n, a), init=ZZ(0))
z += binomial(k,a)*w
end

return z

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

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

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

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 allunique(MP)
@test all(mp -> length(mp) == r, MP)
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