Skip to content

Commit 0e0edc6

Browse files
HarrisonGrodinararslan
authored andcommitted
Update Combinatorics for Julia 1.0 (#69)
* Update Combinatorics for 1.0 * Remove dependence on Compat
1 parent 73198fc commit 0e0edc6

16 files changed

+78
-100
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ language: julia
22
os:
33
- linux
44
julia:
5-
- 0.6
5+
- 0.7
6+
- 1.0
67
- nightly
78
sudo: false
89
notifications:

REQUIRE

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
julia 0.6
2-
Compat 0.59.0
1+
julia 0.7
32
Polynomials
4-
IterTools

src/Combinatorics.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ VERSION < v"0.7.0-beta2.199" && __precompile__()
22

33
module Combinatorics
44

5-
using Compat
65
using Polynomials
7-
using IterTools
86

97
include("numbers.jl")
108
include("factorials.jl")

src/combinations.jl

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ struct Combinations{T}
1111
t::Int
1212
end
1313

14-
Base.start(c::Combinations) = collect(1:c.t)
15-
function Base.next(c::Combinations, s)
14+
function Base.iterate(c::Combinations, s = collect(1:c.t))
15+
(!isempty(s) && s[1] > length(c.a) - c.t + 1) && return
16+
1617
comb = [c.a[si] for si in s]
1718
if c.t == 0
1819
# special case to generate 1 result for t==0
@@ -31,7 +32,6 @@ function Base.next(c::Combinations, s)
3132
end
3233
(comb, s)
3334
end
34-
Base.done(c::Combinations, s) = !isempty(s) && s[1] > length(c.a) - c.t + 1
3535

3636
Base.length(c::Combinations) = binomial(length(c.a), c.t)
3737

@@ -59,7 +59,7 @@ end
5959
Generate combinations of the elements of `a` of all orders. Chaining of order iterators
6060
is eager, but the sequence at each order is lazy.
6161
"""
62-
combinations(a) = IterTools.chain([combinations(a, k) for k = 1:length(a)]...)
62+
combinations(a) = Iterators.flatten([combinations(a, k) for k = 1:length(a)])
6363

6464

6565

@@ -87,7 +87,7 @@ struct CoolLexIterState{T<:Integer}
8787
R3::T
8888
end
8989

90-
function Base.start(C::CoolLexCombinations)
90+
function Base.iterate(C::CoolLexCombinations)
9191
if C.n < 0
9292
throw(DomainError(C.n))
9393
end
@@ -102,10 +102,13 @@ function Base.start(C::CoolLexCombinations)
102102
T = BigInt
103103
end
104104

105-
CoolLexIterState{T}(0, 0, T(1) << C.n, (T(1) << C.t) - 1)
105+
state = CoolLexIterState{T}(0, 0, T(1) << C.n, (T(1) << C.t) - 1)
106+
iterate(C, state)
106107
end
107108

108-
function Base.next(C::CoolLexCombinations, S::CoolLexIterState)
109+
function Base.iterate(C::CoolLexCombinations, S::CoolLexIterState)
110+
(S.R3 & S.R2 != 0) && return
111+
109112
R0 = S.R0
110113
R1 = S.R1
111114
R2 = S.R2
@@ -134,8 +137,6 @@ function _cool_lex_visit(X::Integer)
134137
subset
135138
end
136139

137-
Base.done(C::CoolLexCombinations, S::CoolLexIterState) = (S.R3 & S.R2 != 0)
138-
139140
Base.length(C::CoolLexCombinations) = max(0, binomial(C.n, C.t))
140141

141142

@@ -189,8 +190,9 @@ function multiset_combinations(a, t::Integer)
189190
multiset_combinations(m, f, t)
190191
end
191192

192-
Base.start(c::MultiSetCombinations) = c.ref
193-
function Base.next(c::MultiSetCombinations, s)
193+
function Base.iterate(c::MultiSetCombinations, s = c.ref)
194+
((!isempty(s) && max(s[1], c.t) > length(c.ref)) || (isempty(s) && c.t > 0)) && return
195+
194196
ref = c.ref
195197
n = length(ref)
196198
t = c.t
@@ -218,8 +220,6 @@ function Base.next(c::MultiSetCombinations, s)
218220
end
219221
(comb, s)
220222
end
221-
Base.done(c::MultiSetCombinations, s) =
222-
(!isempty(s) && max(s[1], c.t) > length(c.ref)) || (isempty(s) && c.t > 0)
223223

224224
struct WithReplacementCombinations{T}
225225
a::T
@@ -237,8 +237,9 @@ Generate all combinations with replacement of size `t` from an array `a`.
237237
"""
238238
with_replacement_combinations(a, t::Integer) = WithReplacementCombinations(a, t)
239239

240-
Base.start(c::WithReplacementCombinations) = [1 for i in 1:c.t]
241-
function Base.next(c::WithReplacementCombinations, s)
240+
function Base.iterate(c::WithReplacementCombinations, s = [1 for i in 1:c.t])
241+
(!isempty(s) && s[1] > length(c.a) || c.t < 0) && return
242+
242243
n = length(c.a)
243244
t = c.t
244245
comb = [c.a[si] for si in s]
@@ -261,7 +262,6 @@ function Base.next(c::WithReplacementCombinations, s)
261262
end
262263
(comb, s)
263264
end
264-
Base.done(c::WithReplacementCombinations, s) = !isempty(s) && s[1] > length(c.a) || c.t < 0
265265

266266
## Power set
267267

@@ -276,5 +276,5 @@ subsets.
276276
function powerset(a, min::Integer=0, max::Integer=length(a))
277277
itrs = [combinations(a, k) for k = min:max]
278278
min < 1 && append!(itrs, eltype(a)[])
279-
IterTools.chain(itrs...)
279+
Iterators.flatten(itrs)
280280
end

src/multinomials.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ struct MultiExponents{T}
88
nterms::Int
99
end
1010

11-
Base.start(m::MultiExponents) = start(m.c)
12-
1311
# Standard stars and bars:
1412
# https://en.wikipedia.org/wiki/Stars_and_bars_(combinatorics)
15-
function Base.next(m::MultiExponents, s)
16-
stars, ss = next(m.c, s)
13+
function Base.iterate(m::MultiExponents, s = nothing)
14+
next = s === nothing ? iterate(m.c) : iterate(m.c, s)
15+
next === nothing && return
16+
stars, ss = next
1717

1818
# stars minus their consecutive
1919
# position becomes their index
@@ -25,8 +25,6 @@ function Base.next(m::MultiExponents, s)
2525
result, ss
2626
end
2727

28-
Base.done(m::MultiExponents, s) = done(m.c, s)
29-
3028
Base.length(m::MultiExponents) = length(m.c)
3129

3230
"""

src/partitions.jl

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ end
1616

1717
Base.length(p::IntegerPartitions) = npartitions(p.n)
1818

19-
Base.start(p::IntegerPartitions) = Int[]
20-
Base.done(p::IntegerPartitions, xs) = length(xs) == p.n
21-
Base.next(p::IntegerPartitions, xs) = (xs = nextpartition(p.n,xs); (xs,xs))
19+
function Base.iterate(p::IntegerPartitions, xs = Int[])
20+
length(xs) == p.n && return
21+
xs = nextpartition(p.n,xs)
22+
(xs, xs)
23+
end
2224

2325
"""
2426
partitions(n)
@@ -105,13 +107,15 @@ partitions(n::Integer, m::Integer) =
105107
FixedPartitions(n, m) :
106108
throw(DomainError((n, m), "n and m must be positive"))
107109

108-
Base.start(f::FixedPartitions) = Int[]
109-
function Base.done(f::FixedPartitions, s::Vector{Int})
110-
f.m <= f.n || return true
111-
isempty(s) && return false
112-
return f.m == 1 || s[1]-1 <= s[end]
110+
function Base.iterate(f::FixedPartitions, s::Vector{Int} = Int[])
111+
f.m <= f.n || return
112+
if !isempty(s)
113+
(f.m == 1 || s[1]-1 <= s[end]) && return
114+
end
115+
116+
xs = nextfixedpartition(f.n,f.m,s)
117+
(xs, xs)
113118
end
114-
Base.next(f::FixedPartitions, s::Vector{Int}) = (xs = nextfixedpartition(f.n,f.m,s); (xs,xs))
115119

116120
function nextfixedpartition(n, m, bs)
117121
as = copy(bs)
@@ -177,9 +181,14 @@ number of partitions to generate can be efficiently computed using
177181
"""
178182
partitions(s::AbstractVector) = SetPartitions(s)
179183

180-
Base.start(p::SetPartitions) = (n = length(p.s); (zeros(Int32, n), ones(Int32, n-1), n, 1))
181-
Base.done(p::SetPartitions, s) = s[1][1] > 0
182-
Base.next(p::SetPartitions, s) = nextsetpartition(p.s, s...)
184+
function Base.iterate(p::SetPartitions)
185+
n = length(p.s)
186+
iterate(p, (zeros(Int32, n), ones(Int32, n-1), n, 1))
187+
end
188+
function Base.iterate(p::SetPartitions, s)
189+
s[1][1] > 0 && return
190+
nextsetpartition(p.s, s...)
191+
end
183192

184193
function nextsetpartition(s::AbstractVector, a, b, n, m)
185194
function makeparts(s, a, m)
@@ -255,18 +264,22 @@ partitions(s::AbstractVector, m::Int) =
255264
FixedSetPartitions(s, m) :
256265
throw(DomainError((length(s), m), "length(s) and m must be positive"))
257266

258-
function Base.start(p::FixedSetPartitions)
267+
function Base.iterate(p::FixedSetPartitions)
259268
n = length(p.s)
260269
m = p.m
261-
m <= n ? (vcat(ones(Int, n-m),1:m), vcat(1,n-m+2:n), n) : (Int[], Int[], n)
270+
state = m <= n ? (vcat(ones(Int, n-m),1:m), vcat(1,n-m+2:n), n) : (Int[], Int[], n)
271+
# state consists of:
272+
# vector a of length n describing to which partition every element of s belongs
273+
# vector b of length n describing the first index b[i] that belongs to partition i
274+
# integer n
275+
276+
iterate(p, state)
262277
end
263-
# state consists of:
264-
# vector a of length n describing to which partition every element of s belongs
265-
# vector b of length n describing the first index b[i] that belongs to partition i
266-
# integer n
267278

268-
Base.done(p::FixedSetPartitions, s) = isempty(s[1]) || s[1][1] > 1
269-
Base.next(p::FixedSetPartitions, s) = nextfixedsetpartition(p.s,p.m, s...)
279+
function Base.iterate(p::FixedSetPartitions, s)
280+
(isempty(s[1]) || s[1][1] > 1) && return
281+
nextfixedsetpartition(p.s,p.m, s...)
282+
end
270283

271284
function nextfixedsetpartition(s::AbstractVector, m, a, b, n)
272285
function makeparts(s, a)
@@ -310,7 +323,7 @@ function nextfixedsetpartition(s::AbstractVector, m, a, b, n)
310323
end
311324
b[k] -= 1
312325
b[k+1:m] = n-m+k+1:n
313-
a[1:n] = 1
326+
a[1:n] .= 1
314327
a[b] = 1:m
315328
end
316329
end
@@ -496,4 +509,3 @@ function _ncpart!(a::Int, b::Int, nn::Int, x::Vector, partitions::Vector)
496509
end
497510
end
498511
end
499-

src/permutations.jl

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ function permutations(a, t::Integer)
3939
Permutations(a, t)
4040
end
4141

42-
Base.start(p::Permutations) = collect(1:length(p.a))
43-
Base.next(p::Permutations, s) = nextpermutation(p.a, p.t ,s)
42+
function Base.iterate(p::Permutations, s = collect(1:length(p.a)))
43+
(!isempty(s) && max(s[1], p.t) > length(p.a) || (isempty(s) && p.t > 0)) && return
44+
nextpermutation(p.a, p.t ,s)
45+
end
4446

4547
function nextpermutation(m, t, state)
4648
perm = [m[state[i]] for i in 1:t]
@@ -73,8 +75,6 @@ function nextpermutation(m, t, state)
7375
return (perm, s)
7476
end
7577

76-
Base.done(p::Permutations, s) = !isempty(s) && max(s[1], p.t) > length(p.a) || (isempty(s) && p.t > 0)
77-
7878
struct MultiSetPermutations{T}
7979
m::T
8080
f::Vector{Int}
@@ -134,11 +134,10 @@ function multiset_permutations(m, f::Vector{<:Integer}, t::Integer)
134134
MultiSetPermutations(m, f, t, ref)
135135
end
136136

137-
Base.start(p::MultiSetPermutations) = p.ref
138-
Base.next(p::MultiSetPermutations, s) = nextpermutation(p.m, p.t, s)
139-
Base.done(p::MultiSetPermutations, s) =
140-
!isempty(s) && max(s[1], p.t) > length(p.ref) || (isempty(s) && p.t > 0)
141-
137+
function Base.iterate(p::MultiSetPermutations, s = p.ref)
138+
(!isempty(s) && max(s[1], p.t) > length(p.ref) || (isempty(s) && p.t > 0)) && return
139+
nextpermutation(p.m, p.t, s)
140+
end
142141

143142

144143
"""
@@ -195,9 +194,9 @@ end
195194

196195
# Parity of permutations
197196

198-
const levicivita_lut = cat(3, [0 0 0; 0 0 1; 0 -1 0],
199-
[0 0 -1; 0 0 0; 1 0 0],
200-
[0 1 0; -1 0 0; 0 0 0])
197+
const levicivita_lut = cat([0 0 0; 0 0 1; 0 -1 0],
198+
[0 0 -1; 0 0 0; 1 0 0],
199+
[0 1 0; -1 0 0; 0 0 0]; dims=3)
201200

202201
"""
203202
levicivita(p)

src/youngdiagrams.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ function isrimhook(ξ::SkewDiagram)
5252
l = maximum.x)
5353
youngdiagram = zeros(Int, m, l)
5454
for i = 1:n
55-
youngdiagram[i, μ[i]+1:λ[i]] = 1
55+
youngdiagram[i, μ[i]+1:λ[i]] .= 1
5656
end
5757
for i = n+1:m
58-
youngdiagram[i, 1:λ[i]] = 1
58+
youngdiagram[i, 1:λ[i]] .= 1
5959
end
6060
#Condition 1. Must be edgewise connected
6161
youngdiagramList = Any[]
@@ -114,10 +114,10 @@ function leglength(ξ::SkewDiagram)
114114
l = maximum.x)
115115
youngdiagram = zeros(Int, m, l)
116116
for i = 1:n
117-
youngdiagram[i, μ[i]+1:λ[i]] = 1
117+
youngdiagram[i, μ[i]+1:λ[i]] .= 1
118118
end
119119
for i = n+1:m
120-
youngdiagram[i, 1:λ[i]] = 1
120+
youngdiagram[i, 1:λ[i]] .= 1
121121
end
122122
for i = m:-1:1
123123
any(==(1), youngdiagram[i,:]) && return i-1

test/combinations.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
using Combinatorics
2-
using Compat
3-
using Compat.Test
4-
51
@test [combinations([])...] == []
62
@test [combinations(['a', 'b', 'c'])...] == Any[['a'],['b'],['c'],['a','b'],['a','c'],['b','c'],['a','b','c']]
73

@@ -38,7 +34,7 @@ using Compat.Test
3834
@test_throws DomainError [CoolLexCombinations(-1, 1)...]
3935
@test_throws DomainError [CoolLexCombinations(5, 0)...]
4036
@test [CoolLexCombinations(4,2)...] == Vector[[1,2], [2,3], [1,3], [2,4], [3,4], [1,4]]
41-
@test isa(start(CoolLexCombinations(1000, 20)), Combinatorics.CoolLexIterState{BigInt})
37+
@test isa(iterate(CoolLexCombinations(1000, 20))[2], Combinatorics.CoolLexIterState{BigInt})
4238

4339
# Power set
4440
@test collect(powerset([])) == Any[[]]

test/factorials.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
using Combinatorics
2-
using Compat
3-
using Compat.Test
4-
51
@test factorial(7,3) == 7*6*5*4
62
@test_throws DomainError factorial(3,7)
73
@test_throws DomainError factorial(-3,-7)

0 commit comments

Comments
 (0)