Skip to content

Commit 267f501

Browse files
committed
Finished performance considerations
1 parent 70dbc29 commit 267f501

File tree

3 files changed

+142
-174
lines changed

3 files changed

+142
-174
lines changed

src/messages.jl

Lines changed: 95 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ plotkin_bound(q::T, n::T, d::T, ::Rounding) where T <: Integer =
117117
elias_bassalygo_bound(q::T, n::T, d::T) where T <: Integer =
118118
elias_bassalygo_bound(q::T, n::T, d::T, ::Rounding) where T <: Integer =
119119

120-
121120
function __johnson_bound_core(round_func::Function, q::T, n::T, d::T) where T <: Integer
122121
if isinteger((d - 1) / 2) # is odd
123122
t = T((d - 1) / 2)
@@ -128,8 +127,6 @@ function __johnson_bound_core(round_func::Function, q::T, n::T, d::T) where T <:
128127
end
129128
end
130129
131-
132-
133130
"""
134131
construct_ham_matrix(r::Int, q::Int) -> Matrix
135132
@@ -271,7 +268,7 @@ end
271268
272269
Takes in an array and a word. As long as the word does not mean that the distance is smaller than d, we add w to the array. If we are successful in doing this, return true. Otherwise, return false. *This is a mutating function.*
273270
"""
274-
function push_if_allowed!(C::AbstractArray{T}, w::T, d::Int) where T
271+
function push_if_allowed!(C::AbstractArray{T}, w::T, d::Int) where T <: AbstractWord
275272
isempty(C) && (push!(C, w); return true)
276273

277274
for c in C
@@ -289,7 +286,7 @@ end
289286
290287
Takes in two arrays, A and B. If w is allowed in C given distance d, push to C′. If we are successful in doing this, return true. Otherwise, return false. *This is a mutating function.*
291288
"""
292-
function push_if_allowed!(C::AbstractArray{T}, C′::AbstractArray{T}, w::T, d::Int) where T
289+
function push_if_allowed!(C::AbstractVector{T}, C′::AbstractVector{T}, w::T, d::Int) where T <: AbstractWord
293290
isempty(C) && (push!(C′, w); return true)
294291

295292
for c in C
@@ -307,7 +304,7 @@ end
307304
308305
Takes in an array and a word. As long as the word does not mean that the distance is smaller than d, we replace a with b in the array. Replaces and returns true if allowed; otherwise returns false. *This is a mutating function.*
309306
"""
310-
function replace_if_allowed!(C::AbstractArray, d::Int, ws::Pair)
307+
function replace_if_allowed!(C::AbstractVector{T}, d::Int, ws::Pair) where T <: AbstractWord
311308
w, w′ = ws
312309

313310
for c in C
@@ -319,29 +316,30 @@ function replace_if_allowed!(C::AbstractArray, d::Int, ws::Pair)
319316
replace!(C, ws)
320317
return true
321318
end
322-
323-
function replace_if_allowed!(C::AbstractArray, d::Int, w, w′)
319+
function replace_if_allowed!(C::AbstractVector{T}, d::Int, w::T, w′::T) where T <: AbstractWord
324320
return replace_if_allowed!(C, d, Pair(w, w′))
325321
end
326322

323+
_mutate_codeword(w::Word{N, T}, i::Int, a::T) where {T, N} =
324+
setindex!(w, a, i)
325+
327326
"""
328-
mutate_codeword(w::Tuple{T}, n::Int, i::Int, a::T) -> Tuple
327+
mutate_codeword(w::NonStaticAbstractWord{N, T}, n::Int, i::Int, a::T) where {T, N} -> MVector{N, T}
328+
mutate_codeword(w::Word{N, T}, n::Int, i::Int, a::T) where {T, N} -> MVector{N, T}
329329
330-
Mutates the word w, which is a `Tuple` of length n, changing its iᵗʰ index to a.
330+
Mutates the word w, which is an `MVector` of length N, changing its iᵗʰ index to a.
331331
"""
332-
function mutate_codeword(w::Union{Tuple{T}, NTuple{N, T}}, n::Int, i::Int, a::T) where {N, T}
333-
w̲ = collect(w)
334-
w̲[i] = a
335-
336-
return ntuple(j -> w̲[j], n)
337-
end
332+
mutate_codeword(w::NonStaticAbstractWord{N, T}, i::Int, a::T) where {T, N} =
333+
_mutate_codeword(Word{N, T}(w), i, a)
334+
mutate_codeword(w::Word{N, T}, n::Int, i::Int, a::T) where {T, N} =
335+
_mutate_codeword(w, i, a)
338336

339337
"""
340-
get_all_words(Σ::Alphabet, q::Int, n::Int) -> Array{Tuple{Symbol}, 1}
341-
get_all_words(Σ::Alphabet, n::Int) -> Array{Tuple{Symbol}, 1}
342-
get_all_words(Σ::AbstractArray, q::Int, n::Int) -> Array{Tuple{Symbol}, 1}
343-
get_all_words(Σ::AbstractArray, n::Int) -> Array{Tuple{Symbol}, 1}
344-
get_all_words(q::Int, n::Int) -> Array{Tuple{Symbol}, 1}
338+
get_all_words(Σ::Alphabet{N}, q::Int, n::Int) -> Codewords{M}
339+
get_all_words(Σ::Alphabet{N}, n::Int) -> Codewords{M}
340+
get_all_words(Σ::AbstractArray, q::Int, n::Int) -> Codewords{M}
341+
get_all_words(Σ::AbstractArray, n::Int) -> Codewords{M}
342+
get_all_words(q::Int, n::Int) -> Codewords{M}
345343
346344
Get the universe of all codewords of a given alphabet. The alphabet will be uniquely generated if none is given.
347345
@@ -353,31 +351,26 @@ Parameters:
353351
- 𝒰::AbstractArray: The universe of all codewords of q many letters of block length n.
354352
355353
Returns:
356-
- Array{Tuple{Symbol}, 1}: An array of codewords. Each codewords is a tuple, and each character in said word is a symbol.
354+
- Codewords{M}: An array of codewords, each of length `M`. Each codewords is a tuple, and each character in said word is a symbol.
357355
"""
358-
359-
function get_all_words(Σ::Alphabet, q::Int, n::Int)
360-
return CodeUniverseIterator(UniverseParameters(Σ, q, n))
361-
end
362-
363-
get_all_words(Σ::Alphabet, n::Int) =
364-
get_all_words(Σ, length(unique(Σ)), n) # if alphabet is given, then q is the length of that alphabet
365-
get_all_words(Σ::AbstractArray, q::Int, n::Int) =
366-
get_all_words(Alphabet(Σ), q, Val(n))
356+
get_all_words(Σ::Alphabet{N}, q::Int, n::Int) where {N} =
357+
collect(CodeUniverseIterator(UniverseParameters(Σ, q, n)))
358+
get_all_words(Σ::Alphabet{N}, n::Int) where {N} =
359+
get_all_words(Σ, length(Set(Σ)), n) # if alphabet is given, then q is the length of that alphabet
367360
get_all_words(Σ::AbstractArray, n::Int) =
368-
get_all_words(Alphabet(Σ), length(unique(Σ)), n) # if alphabet is given, then q is the length of that alphabet
361+
get_all_words(Alphabet(Σ), length(Set(Σ)), n) # if alphabet is given, then q is the length of that alphabet
369362
get_all_words(q::Int, n::Int) =
370-
get_all_words(Alphabet(Symbol[gensym() for _ in 1:q]), q, n) # generate symbols if no alphabet is given
363+
get_all_words(genalphabet(q), q, n) # generate symbols if no alphabet is given
371364

372365
"""
373-
get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Array{Tuple{Symbol}, 1}
374-
get_codewords_greedy(𝒰::UniverseParameters, d::Int) -> Array{Tuple{Symbol}, 1}
375-
get_codewords_greedy(Σ::Alphabet, q::Int, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
376-
get_codewords_greedy(Σ::Alphabet, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
377-
get_codewords_greedy(q::Int, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
378-
get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
379-
get_codewords_greedy(Σ::AbstractArray, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
380-
get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Array{Tuple{Symbol}, 1}
366+
get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Codewords{M}
367+
get_codewords_greedy(𝒰::UniverseParameters, d::Int) -> Codewords{M}
368+
get_codewords_greedy(Σ::Alphabet{N}, q::Int, n::Int, d::Int) -> Codewords{M}
369+
get_codewords_greedy(Σ::Alphabet{N}, n::Int, d::Int) -> Codewords{M}
370+
get_codewords_greedy(q::Int, n::Int, d::Int) -> Codewords{M}
371+
get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int) -> Codewords{M}
372+
get_codewords_greedy(Σ::AbstractArray, n::Int, d::Int) ->Codewords{M}
373+
get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Codewords{M}
381374
382375
Search through the universe of all codewords and find a code of block length n and distance d, using the alphabet Σ. The alphabet will be uniquely generated if none is given.
383376
@@ -389,21 +382,20 @@ Parameters:
389382
- d::Int: The minimum distance between words in the code.
390383
391384
Returns:
392-
- Array{Tuple{Symbol}, 1}: An array of codewords. Each codewords is a tuple, and each character in said word is a symbol.
385+
- Codewords{M}: An array of codewords, each of length `M`. Each codewords is a tuple, and each character in said word is a symbol.
393386
"""
394387
function get_codewords_greedy(𝒰::UniverseParameters, d::Int)
395-
C = Tuple[]
388+
C = eltype(𝒰)[]
396389

397390
for wᵢ in CodeUniverseIterator(𝒰)
398391
push_if_allowed!(C, wᵢ, d)
399392
end
400393

401394
return C
402395
end
403-
404-
get_codewords_greedy(Σ::Alphabet, q::Int, n::Int, d::Int) =
396+
get_codewords_greedy(Σ::Alphabet{N}, q::Int, n::Int, d::Int) where {N} =
405397
get_codewords_greedy(UniverseParameters(Σ, q, n), d)
406-
get_codewords_greedy(Σ::Alphabet, n::Int, d::Int) =
398+
get_codewords_greedy(Σ::Alphabet{N}, n::Int, d::Int) where {N} =
407399
get_codewords_greedy(UniverseParameters(Σ, n), d)
408400
get_codewords_greedy(q::Int, n::Int, d::Int) =
409401
get_codewords_greedy(UniverseParameters(q, n), d)
@@ -415,18 +407,18 @@ get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractAr
415407
get_codewords_greedy(Alphabet(Σ), q, n, d, 𝒰)
416408

417409

418-
argmaxminima(A::AbstractArray; dims::Int) = getindex(argmin(A, dims=dims), argmax(argmin(A, dims=dims)))
419-
maxminima(A::AbstractArray; dims::Int) = getindex(minimum(A, dims=dims), maximum(minimum(A, dims=dims)))
420-
argminmaxima(A::AbstractArray; dims::Int) = getindex(argmax(A, dims=dims), argmin(argmax(A, dims=dims)))
421-
minmaxima(A::AbstractArray; dims::Int) = getindex(maximum(A, dims=dims), minimum(maximum(A, dims=dims)))
410+
argmaxminima(A::AbstractArray; dims::Int) = getindex(argmin(A, dims = dims), argmax(argmin(A, dims = dims)))
411+
maxminima(A::AbstractArray; dims::Int) = getindex(minimum(A, dims = dims), maximum(minimum(A, dims = dims)))
412+
argminmaxima(A::AbstractArray; dims::Int) = getindex(argmax(A, dims = dims), argmin(argmax(A, dims = dims)))
413+
minmaxima(A::AbstractArray; dims::Int) = getindex(maximum(A, dims = dims), minimum(maximum(A, dims = dims)))
422414

423415
"""
424-
get_codewords_random(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Array{Tuple{Symbol}, 1}
425-
get_codewords_random(Σ::AbstractArray, n::Int, d::Int, 𝒰::AbstractArray) -> Array{Tuple{Symbol}, 1}
426-
get_codewords_random(q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Array{Tuple{Symbol}, 1}
427-
get_codewords_random(Σ::AbstractArray, q::Int, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
428-
get_codewords_random(Σ::AbstractArray, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
429-
get_codewords_random(q::Int, n::Int, d::Int) -> Array{Tuple{Symbol}, 1}
416+
get_codewords_random(Σ::Alphabet{N}, q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Codewords{M}
417+
get_codewords_random(Σ::Alphabet{N}, n::Int, d::Int, 𝒰::AbstractArray) -> Codewords{M}
418+
get_codewords_random(q::Int, n::Int, d::Int, 𝒰::AbstractArray) -> Codewords{M}
419+
get_codewords_random(Σ::AbstractArray, q::Int, n::Int, d::Int) -> Codewords{M}
420+
get_codewords_random(Σ::AbstractArray, n::Int, d::Int) -> Codewords{M}
421+
get_codewords_random(q::Int, n::Int, d::Int) -> Codewords{M}
430422
431423
Search through the universe of all codewords at random and find a code of block length n and distance d, using the alphabet Σ. The alphabet will be uniquely generated if none is given.
432424
@@ -438,32 +430,32 @@ Parameters:
438430
- 𝒰::AbstractArray: The universe of all codewords of q many letters of block length n.
439431
440432
Returns:
441-
- Array{Tuple{Symbol}, 1}: An array of codewords. Each codewords is a tuple, and each character in said word is a symbol.
433+
- Codewords{M}: An array of codewords, each of length `M`. Each codewords is a tuple, and each character in said word is a symbol.
442434
"""
443-
function get_codewords_random(𝒰::UniverseParameters, d::Int; m::Int=1000)
444-
C = Tuple[]
435+
function get_codewords_random(𝒰::UniverseParameters, d::Int; m::Int = 1000)
436+
C = eltype(𝒰)[]
445437

446438
starting_word = rand(𝒰) # get a random word in the code start
447439
push!(C, starting_word)
448440

449441
for _ in 1:length(𝒰)
450-
C′ = Tuple[]
442+
C′ = eltype(𝒰)[]
451443
for _ in 1:m
452444
push_if_allowed!(C, C′, rand(𝒰), d) # if allowed in C, push to C′
453445
end
454446
isempty(C′) && break
455447
# [push_if_allowed!(C, C′, w, d) for _ in 1:m]
456-
distances = [hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′]
448+
distances = Int[hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′]
457449
best_word = getindex(C′, getindex(argmaxminima(distances, dims = 1), 2))
458450
push!(C, best_word)
459451
end
460452

461453
return C
462454
end
463455

464-
get_codewords_random(Σ::Alphabet, q::Int, n::Int, d::Int; m::Int=1000) =
456+
get_codewords_random(Σ::Alphabet{N}, q::Int, n::Int, d::Int; m::Int=1000) where {N} =
465457
get_codewords_random(UniverseParameters(Σ, q, n), d, m=m)
466-
get_codewords_random(Σ::Alphabet, n::Int, d::Int; m::Int=1000) =
458+
get_codewords_random(Σ::Alphabet{N}, n::Int, d::Int; m::Int=1000) where {N} =
467459
get_codewords_random(UniverseParameters(Σ, n), d, m=m)
468460
get_codewords_random(q::Int, n::Int, d::Int; m::Int=1000) =
469461
get_codewords_random(UniverseParameters(q, n), d, m=m)
@@ -475,43 +467,43 @@ get_codewords_random(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractAr
475467
get_codewords_random(Alphabet(Σ), q, n, d, 𝒰, m=m)
476468

477469

478-
using Mmap
479-
function get_codewords_random_mmap(mmappath::AbstractString, 𝒰::UniverseParameters, d::Int)
480-
io = open(mmappath, "r+") # allow read and write
481-
# write(s, size(A,2))
482-
# read(s, Int)
483-
# close(s)
484-
# B = Mmap.mmap(io, BitArray, (25,30000))
485-
# Mmap.sync!(B);
486-
# close(io);
487-
# rm("mmap.bin")
488-
starting_word = rand(𝒰) # get a random word in the code start
489-
push!(C, starting_word)
490-
491-
for _ in 1:length(𝒰)
492-
C′ = Tuple[]
493-
for _ in 1:m
494-
push_if_allowed!(C, C′, rand(𝒰), d) # if allowed in C, push to C′
495-
end
496-
isempty(C′) && break
497-
# [push_if_allowed!(C, C′, w, d) for _ in 1:m]
498-
distances = [hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′]
499-
best_word = getindex(C′, getindex(argmaxminima(distances, dims = 1), 2))
500-
push!(C, best_word)
501-
end
502-
503-
return C
504-
end
470+
# using Mmap
471+
# function get_codewords_random_mmap(mmappath::AbstractString, 𝒰::UniverseParameters, d::Int)
472+
# io = open(mmappath, "r+") # allow read and write
473+
# # write(s, size(A,2))
474+
# # read(s, Int)
475+
# # close(s)
476+
# # B = Mmap.mmap(io, BitArray, (25,30000))
477+
# # Mmap.sync!(B);
478+
# # close(io);
479+
# # rm("mmap.bin")
480+
# starting_word = rand(𝒰) # get a random word in the code start
481+
# push!(C, starting_word)
482+
#
483+
# for _ in 1:length(𝒰)
484+
# C′ = Tuple[]
485+
# for _ in 1:m
486+
# push_if_allowed!(C, C′, rand(𝒰), d) # if allowed in C, push to C′
487+
# end
488+
# isempty(C′) && break
489+
# # [push_if_allowed!(C, C′, w, d) for _ in 1:m]
490+
# distances = [hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′]
491+
# best_word = getindex(C′, getindex(argmaxminima(distances, dims = 1), 2))
492+
# push!(C, best_word)
493+
# end
494+
#
495+
# return C
496+
# end
505497

506498
# get_codewords_random(𝒰::UniverseParameters, d::Int) = get_codewords_random(joinpath(tempdir(), "mmap.bin"), 𝒰, d)
507499

508500
"""
509-
get_codewords(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray; m::Int=10) -> Array{Tuple{Symbol}, 1}
510-
get_codewords(Σ::AbstractArray, n::Int, d::Int, 𝒰::AbstractArray; m::Int=10) -> Array{Tuple{Symbol}, 1}
511-
get_codewords(q::Int, n::Int, d::Int, 𝒰::AbstractArray; m::Int=10) -> Array{Tuple{Symbol}, 1}
512-
get_codewords(Σ::AbstractArray, q::Int, n::Int, d::Int; m::Int=10) -> Array{Tuple{Symbol}, 1}
513-
get_codewords(Σ::AbstractArray, n::Int, d::Int; m::Int=10) -> Array{Tuple{Symbol}, 1}
514-
get_codewords(q::Int, n::Int, d::Int; m::Int=10) -> Array{Tuple{Symbol}, 1}
501+
get_codewords(Σ::Alphabet{N}, q::Int, n::Int, d::Int, 𝒰::AbstractArray; m::Int=10) -> Codewords{M}
502+
get_codewords(Σ::Alphabet{N}, n::Int, d::Int, 𝒰::AbstractArray; m::Int=10) -> Codewords{M}
503+
get_codewords(q::Int, n::Int, d::Int, 𝒰::AbstractArray; m::Int=10) -> Codewords{M}
504+
get_codewords(Σ::AbstractArray, q::Int, n::Int, d::Int; m::Int=10) -> Codewords{M}
505+
get_codewords(Σ::AbstractArray, n::Int, d::Int; m::Int=10) -> Codewords{M}
506+
get_codewords(q::Int, n::Int, d::Int; m::Int=10) -> Codewords{M}
515507
516508
Use function `get_codewords_random` m many times, and `get_codewords_greedy`. Return the code with the greatest number of words. The alphabet will be uniquely generated if none is given. You can omit Σ and 𝒰. You can omit q if Σ is given.
517509
@@ -524,11 +516,11 @@ Parameters:
524516
- m::Int (kwarg): Try a random code m many times.
525517
526518
Returns:
527-
- Array{Tuple{Symbol}, 1}: An array of codewords. Each codewords is a tuple, and each character in said word is a symbol.
519+
- Codewords{M}: An array of codewords, each of length `M`. Each codewords is a tuple, and each character in said word is a symbol.
528520
"""
529521
function get_codewords(𝒰::UniverseParameters, d::Int; m::Int=10)
530522
code_size = 0
531-
C = Tuple[]
523+
C = eltype(𝒰)[]
532524

533525

534526
for _ in 1:m
@@ -550,9 +542,9 @@ function get_codewords(𝒰::UniverseParameters, d::Int; m::Int=10)
550542
return C
551543
end
552544

553-
get_codewords(Σ::Alphabet, q::Int, n::Int, d::Int; m::Int=10) =
545+
get_codewords(Σ::Alphabet{N}, q::Int, n::Int, d::Int; m::Int=10) where {N} =
554546
get_codewords(UniverseParameters(Σ, q, n), d, m=m)
555-
get_codewords(Σ::Alphabet, n::Int, d::Int; m::Int=10) =
547+
get_codewords(Σ::Alphabet{N}, n::Int, d::Int; m::Int=10) where {N} =
556548
get_codewords(UniverseParameters(Σ, n), d, m=m)
557549
get_codewords(q::Int, n::Int, d::Int; m::Int=10) =
558550
get_codewords(UniverseParameters(q, n), d, m=m)
@@ -564,7 +556,7 @@ get_codewords(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray; m:
564556
get_codewords(Alphabet(Σ), q, n, d, 𝒰, m=m)
565557

566558
"""
567-
get_codewords(G::AbstractArray, m::Int) -> Array{Tuple{Symbol}, 1}
559+
get_codewords(G::AbstractArray, m::Int) -> Codewords{M}
568560
569561
Get codewords of a code from the generating matrix under a finite field of modulo m. Precisely, computes all linear combinations of the rows of the generating matrix.
570562
@@ -573,7 +565,7 @@ Parameters:
573565
- m::Int: The bounds of the finite field (i.e., the molulus you wish to work in).
574566
575567
Returns:
576-
- Array{Tuple{Symbol}, 1}: An array of codewords. Each codewords is a tuple, and each character in said word is a symbol.
568+
- Codewords{M}: An array of codewords, each of length `M`. Each codewords is a tuple, and each character in said word is a symbol.
577569
"""
578570
function get_codewords(G::AbstractArray, m::Int)
579571
codewords = Vector()
@@ -583,7 +575,7 @@ function get_codewords(G::AbstractArray, m::Int)
583575
rows[i] = [G[i, j] for j in 1:size(G, 2)]
584576
end
585577

586-
for c in Base.Iterators.product([0:m-1 for i in 1:size(G, 1)]...)
578+
for c in Base.Iterators.product([0:m-1 for _ in 1:size(G, 1)]...)
587579
word = Ref(c[1]) .* rows[1]
588580

589581
for i in 2:size(G, 1)

0 commit comments

Comments
 (0)