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

function combinations(n::Integer, k::Integer)
return sort(AbstractAlgebra.combinations(n, k))
end

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

Return an iterator over all combinations of `k` elements of `v`.
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.combinations([1, 2, 3, 4], 2))
6-element Vector{Vector{Int64}}:
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]
```
"""
function combinations(v::AbstractVector{T}, k::Integer) where {T}
reorder(v, inds) = [v[i] for i in inds]
return (reorder(v, inds) for inds in combinations(length(v), k))
end

function multicombinations(n::Integer, k::Integer)
return sort!(
reverse.(
Expand Down
18 changes: 0 additions & 18 deletions experimental/LieAlgebras/test/Combinatorics-test.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
@testset "LieAlgebras.Combinatorics" begin
@testset "combinations" begin
combinations = Oscar.LieAlgebras.combinations

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

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

@testset "multicombinations" begin
Comment thread
lgoettgens marked this conversation as resolved.
multicombinations = Oscar.LieAlgebras.multicombinations

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

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

# Examples

```jldoctest
julia> C = combinations(4, 3)
Iterator over the 3-combinations of 1:4

julia> collect(C)
4-element Vector{Combination{Int64}}:
[1, 2, 3]
[1, 2, 4]
[1, 3, 4]
[2, 3, 4]
```
"""
combinations(n::Int, k::Int) = Combinations(1:n, k)

@doc raw"""
combinations(v::AbstractVector, k::Int)

Return an iterator over all `k`-combinations of a given vector `v` produced in
lexicographically ascending order of the indices.

# Examples

```jldoctest
julia> C = combinations(['a', 'b', 'c', 'd'], 3)
Iterator over the 3-combinations of ['a', 'b', 'c', 'd']

julia> collect(C)
4-element Vector{Combination{Char}}:
['a', 'b', 'c']
['a', 'b', 'd']
['a', 'c', 'd']
['b', 'c', 'd']
```
"""
function combinations(v::AbstractVector{T}, k::Int) where T
return Combinations(v, k)
end

Combinations(v::AbstractArray{T}, k::Int) where T = Combinations(v, length(v), k)

@inline function Base.iterate(C::Combinations, state = [min(C.k - 1, i) for i in 1:C.k])
if C.k == 0 # special case to generate 1 result for k = 0
if isempty(state)
return Combination(eltype(C.v)[]), [0]
end
return nothing
end
for i in C.k:-1:1
state[i] += 1
if state[i] > (C.n - (C.k - i))
continue
end
for j in i+1:C.k
state[j] = state[j - 1] + 1
end
break
end
if state[1] > C.n - C.k + 1
return nothing
end
return Combination(C.v[state]), state
end

Base.length(C::Combinations) = binomial(C.n, C.k)

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

function Base.show(io::IO, C::Combinations)
print(io, "Iterator over the ", C.k, "-combinations of ", C.v)
end

################################################################################
#
# Array-like functionality
#
################################################################################

function Base.show(io::IO, ::MIME"text/plain", P::Combination)
p = data(P)
if isempty(p)
print(io, "Empty combination")
return
end
print(io, p)
end

data(P::Combination) = P.v

function Base.size(P::Combination)
return size(data(P))
end

function Base.length(P::Combination)
return length(data(P))
end

function Base.getindex(P::Combination, i::IntegerUnion)
return getindex(data(P), Int(i))
end

function Base.setindex!(P::Combination, x::IntegerUnion, i::IntegerUnion)
return setindex!(data(P), x, i)
end

function Base.copy(P::Combination)
return Combination(copy(data(P)))
end
18 changes: 18 additions & 0 deletions src/Combinatorics/EnumerativeCombinatorics/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -377,3 +377,21 @@ struct StandardTableauxFixedBoxNum{T<:IntegerUnion}
return new{T}(box_num)
end
end

################################################################################
#
# Combination(s)
#
################################################################################

struct Combinations{T}
v::T
n::Int
k::Int
end

struct Combination{T} <: AbstractVector{T}
v::Vector{T}
end


2 changes: 2 additions & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export CartierDivisor
export ClosedEmbedding
export ClosedSubvarietyOfToricVariety
export CohomologyClass
export Combination
export Composition
export Cone
export CoveredScheme
Expand Down Expand Up @@ -396,6 +397,7 @@ export cokernel
export collector
export coloops
export column
export combinations
export combinatorial_symmetries
export comm
export comm!
Expand Down
45 changes: 45 additions & 0 deletions test/Combinatorics/EnumerativeCombinatorics/combinations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@testset "combinations" begin
let
C = combinations(4, 3)
@test length(C) == 4
@test collect(C) == [[1, 2, 3],
[1, 2, 4],
[1, 3, 4],
[2, 3, 4]]
@test eltype(C) === Combination{Int}
C = combinations(100, 3)
@test length(C) == binomial(100, 3)
C = combinations(4, 5)
@test length(C) == 0

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

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

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

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

@test collect(combinations(0, 0)) == [Int[]]
end
Loading