Skip to content
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
37 changes: 0 additions & 37 deletions experimental/LieAlgebras/src/Combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,6 @@
# Most implementations here are quite slow and should be replaced by a
# more efficient implementation.

function multicombinations(n::Integer, k::Integer)
return sort!(
reverse.(
reduce(
vcat, data.(partitions(i, k, 1, n)) for i in 0:(k * n); init=Vector{Int}[]
)::Vector{Vector{Int}}
),
)
end

@doc raw"""
Oscar.LieAlgebras.multicombinations(v::AbstractVector{T}, k::Integer) where {T}

Return an iterator over all combinations of `k` elements of `v` with repetitions.
In each iteration, the elements are returned in the order they appear in `v`.
The order of the combinations is lexicographic.

```jldoctest
julia> collect(Oscar.LieAlgebras.multicombinations([1, 2, 3, 4], 2))
10-element Vector{Vector{Int64}}:
[1, 1]
[1, 2]
[1, 3]
[1, 4]
[2, 2]
[2, 3]
[2, 4]
[3, 3]
[3, 4]
[4, 4]
```
"""
function multicombinations(v::AbstractVector{T}, k::Integer) where {T}
reorder(v, inds) = [v[i] for i in inds]
return (reorder(v, inds) for inds in multicombinations(length(v), k))
end

function permutations(n::Integer)
return map(Vector{Int}, AbstractAlgebra.SymmetricGroup(n))
end
Expand Down
8 changes: 4 additions & 4 deletions experimental/LieAlgebras/src/LieAlgebraModule.jl
Original file line number Diff line number Diff line change
Expand Up @@ -615,9 +615,9 @@ Construct the the Lie algebra module over `L` of dimension `dimV` given by
`transformation_matrices` and with basis element names `s`.

* `transformation_matrices`: The action of the $i$-th basis element of `L`
on some element $v$ of the constructed module is given by right multiplication
on some element $v$ of the constructed module is given by right multiplication
of the matrix `transformation_matrices[i]` to the coefficient vector of $v$.
* `s`: A vector of basis element names. This is
* `s`: A vector of basis element names. This is
`[Symbol("v_$i") for i in 1:dimV]` by default.
* `check`: If `true`, check that the structure constants are anti-symmetric and
satisfy the Jacobi identity. This is `true` by default.
Expand All @@ -644,7 +644,7 @@ of `L`, and $v_i$ the $i$-th standard basis vector of `V`.
Then the entry `struct_consts[i,j][k]` is a scalar $a_{i,j,k}$
such that $x_i * v_j = \sum_k a_{i,j,k} v_k$.

* `s`: A vector of basis element names. This is
* `s`: A vector of basis element names. This is
`[Symbol("v_$i") for i in 1:dimV]` by default.
* `check`: If `true`, check that the structure constants are anti-symmetric and
satisfy the Jacobi identity. This is `true` by default.
Expand Down Expand Up @@ -1151,7 +1151,7 @@ function symmetric_power(
L = base_lie_algebra(V)
R = coefficient_ring(V)
dim_S = binomial(dim(V) + k - 1, k)
ind_map = collect(multicombinations(1:dim(V), k))
ind_map = collect(multicombinations(dim(V), k))

T, _ = tensor_power(V, k; cached)
S_to_T_mat = zero_matrix(R, dim_S, dim(T))
Expand Down
49 changes: 0 additions & 49 deletions experimental/LieAlgebras/test/Combinatorics-test.jl
Original file line number Diff line number Diff line change
@@ -1,53 +1,4 @@
@testset "LieAlgebras.Combinatorics" begin
@testset "multicombinations" begin
multicombinations = Oscar.LieAlgebras.multicombinations

@test collect(multicombinations(0, 0)) == [Int[]]
@test collect(multicombinations(0, 1)) == []

for n in 1:8, k in 1:n
@test collect(multicombinations(n, k)) == collect(multicombinations(1:n, k))
end

@test collect(multicombinations(["1", "2", "3", "4"], 0)) == [String[]]
@test collect(multicombinations(["1", "2", "3", "4"], 1)) ==
[["1"], ["2"], ["3"], ["4"]]
@test collect(multicombinations(["1", "2", "3", "4"], 2)) == [
["1", "1"],
["1", "2"],
["1", "3"],
["1", "4"],
["2", "2"],
["2", "3"],
["2", "4"],
["3", "3"],
["3", "4"],
["4", "4"],
]
@test collect(multicombinations(["1", "2", "3", "4"], 3)) == [
["1", "1", "1"],
["1", "1", "2"],
["1", "1", "3"],
["1", "1", "4"],
["1", "2", "2"],
["1", "2", "3"],
["1", "2", "4"],
["1", "3", "3"],
["1", "3", "4"],
["1", "4", "4"],
["2", "2", "2"],
["2", "2", "3"],
["2", "2", "4"],
["2", "3", "3"],
["2", "3", "4"],
["2", "4", "4"],
["3", "3", "3"],
["3", "3", "4"],
["3", "4", "4"],
["4", "4", "4"],
]
end

@testset "permutations" begin
permutations = Oscar.LieAlgebras.permutations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ include("tableaux.jl")
include("weak_compositions.jl")
include("compositions.jl")
include("combinations.jl")
include("multicombinations.jl")
86 changes: 86 additions & 0 deletions src/Combinatorics/EnumerativeCombinatorics/multicombinations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
@doc raw"""
multicombinations(n::IntegerUnion, k::IntegerUnion)

Return an iterator over all $k$-combinations of ${1,...,n}$ with repetition,
produced in lexicographically ascending order.

# Examples

```jldoctest
julia> C = multicombinations(4, 2)
Iterator over the 2-combinations of 1:4 with repetition

julia> collect(C)
10-element Vector{Combination{Int64}}:
[1, 1]
[1, 2]
[1, 3]
[1, 4]
[2, 2]
[2, 3]
[2, 4]
[3, 3]
[3, 4]
[4, 4]
```
"""
multicombinations(n::T, k::T) where T<:IntegerUnion = MultiCombinations(Base.oneto(n), n, k)


@doc raw"""
multicombinations(v::AbstractVector{T}, k::Integer) where {T}

Return an iterator over all combinations of `k` elements of `v` with repetitions.
In each iteration, the elements are returned in the order they appear in `v`.
The order of the combinations is lexicographic.

```jldoctest
julia> collect(multicombinations(['a', 'b', 'c'], 2))
6-element Vector{Combination{Char}}:
['a', 'a']
['a', 'b']
['a', 'c']
['b', 'b']
['b', 'c']
['c', 'c']
```
"""
multicombinations(v::AbstractVector, k::IntegerUnion) = MultiCombinations(v, k)

MultiCombinations(v::AbstractArray, k::T) where {T<:IntegerUnion} = MultiCombinations(v, T(length(v)), k)


@inline function Base.iterate(C::MultiCombinations{<:AbstractVector{T}, U}, state::Vector{U} = C.k == 0 ? U[] : (s = ones(U, C.k); s[Int(C.k)] = U(0); s)) where {T, U<:IntegerUnion}
if is_zero(C.k) # special case to generate 1 result for k = 0
if isempty(state)
return Combination{T}(T[]), U[0]
end
return nothing
end
for i in C.k:U(-1):U(1)
state[i] += 1
if state[i] > C.n
continue
end
for j in i+1:C.k
state[j] = state[i]
end
break
end
if state[1] > C.n
return nothing
end
return Combination{T}(C.v[state]), state
end

Base.length(C::MultiCombinations) = binomial(Int(C.n)+Int(C.k)-1, Int(C.k))

Base.eltype(::Type{<:MultiCombinations{T}}) where {T} = Combination{eltype(T)}

function Base.show(io::IO, C::MultiCombinations{<:Base.OneTo})
print(io, "Iterator over the ", C.k, "-combinations of ", 1:C.n, " with repetition")
end

function Base.show(io::IO, C::MultiCombinations)
print(io, "Iterator over the ", C.k, "-combinations of ", C.v, " with repetition")
end
12 changes: 12 additions & 0 deletions src/Combinatorics/EnumerativeCombinatorics/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,15 @@ end
struct Combination{T} <: AbstractVector{T}
v::Vector{T}
end

################################################################################
#
# Multicombination(s)
#
################################################################################

struct MultiCombinations{T, U<:IntegerUnion}
v::T
n::U
k::U
end
1 change: 1 addition & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,7 @@ export mul!
export multi_hilbert_function
export multi_hilbert_series
export multi_hilbert_series_reduced
export multicombinations
export multipartition
export multipartitions
export multiplication_induced_morphism
Expand Down
85 changes: 85 additions & 0 deletions test/Combinatorics/EnumerativeCombinatorics/multicombinations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
@testset "multicombinations" begin
let
C = multicombinations(3, 2)
@test length(C) == 6
@test collect(C) == [[1, 1],
[1, 2],
[1, 3],
[2, 2],
[2, 3],
[3, 3]]
@test eltype(C) === Combination{Int}
C = multicombinations(100, 3)
@test length(C) == binomial(102, 3)

C = multicombinations(Int16(2), Int16(2))
@test length(C) == 3
@test collect(C) == [[1, 1],
[1, 2],
[2, 2]]
@test eltype(C) === Combination{Int16}

C = multicombinations('a':'c', 3)
@test length(C) == 10
@test collect(C) == [['a', 'a', 'a'],
['a', 'a', 'b'],
['a', 'a', 'c'],
['a', 'b', 'b'],
['a', 'b', 'c'],
['a', 'c', 'c'],
['b', 'b', 'b'],
['b', 'b', 'c'],
['b', 'c', 'c'],
['c', 'c', 'c']]
@test eltype(C) === Combination{Char}
end

for n in 1:5, k in 1:n
@test collect(multicombinations(n, k)) == collect(multicombinations(1:n, k))
end

@test collect(multicombinations(["1", "2", "3", "4"], 0)) == [String[]]
@test collect(multicombinations(["1", "2", "3", "4"], 1)) == [["1"], ["2"], ["3"], ["4"]]
@test collect(multicombinations(["1", "2", "3", "4"], 2)) == [
["1", "1"],
["1", "2"],
["1", "3"],
["1", "4"],
["2", "2"],
["2", "3"],
["2", "4"],
["3", "3"],
["3", "4"],
["4", "4"],
]
@test collect(multicombinations(["1", "2", "3", "4"], 3)) == [
["1", "1", "1"],
["1", "1", "2"],
["1", "1", "3"],
["1", "1", "4"],
["1", "2", "2"],
["1", "2", "3"],
["1", "2", "4"],
["1", "3", "3"],
["1", "3", "4"],
["1", "4", "4"],
["2", "2", "2"],
["2", "2", "3"],
["2", "2", "4"],
["2", "3", "3"],
["2", "3", "4"],
["2", "4", "4"],
["3", "3", "3"],
["3", "3", "4"],
["3", "4", "4"],
["4", "4", "4"],
]

v = collect(multicombinations(5, 3))
@test issorted(v)
@test allunique(v)

@test collect(multicombinations(0, 0)) == [Int[]]
Comment thread
fingolfin marked this conversation as resolved.
@test collect(multicombinations(0, 1)) == []

end
Loading