diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 7ccf0ed..e64a6e9 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -10,7 +10,7 @@ pipe_to_function_call = true short_to_long_function_def = false force_long_function_def = false long_to_short_function_def = false -always_use_return = true +always_use_return = false whitespace_in_kwargs = true annotate_untyped_fields_with_any = false format_docstrings = false diff --git a/examples/bounds.jl b/examples/bounds.jl index c849b2d..6cb364a 100755 --- a/examples/bounds.jl +++ b/examples/bounds.jl @@ -57,7 +57,7 @@ function make_integer_csv(stop_at::Integer) CSV.write(data_file_desktop, D) CSV.write(data_file_other, D) - return println("\nWrote data to $(data_file_other).") + println("\nWrote data to $(data_file_other).") end function bound_comparison(stop_at::Integer)::Tuple{Int, Array{Array{Number, 1}}} @@ -119,7 +119,7 @@ function plot_bound_comparison(stop_at::Integer) println("Data written to $(data_file_desktop) and $(data_file_other)") `Rscript --vanilla "~"/projects/CodingTheory.jl/other/regression-tree.R $data_file_other $stop_at` - return println("Regression tree saved at $(joinpath(dirname(dirname(@__FILE__)), "other", "Rplots_$(stop_at).pdf"))",) + println("Regression tree saved at $(joinpath(dirname(dirname(@__FILE__)), "other", "Rplots_$(stop_at).pdf"))",) end # make_integer_csv constructs a csv file which looks for hamming bounds (given certain conditions) that are integers before rounding diff --git a/examples/get_codewords_time_analysis.jl b/examples/get_codewords_time_analysis.jl index 5b9e82e..4a98c0d 100755 --- a/examples/get_codewords_time_analysis.jl +++ b/examples/get_codewords_time_analysis.jl @@ -54,7 +54,7 @@ function graphing_time(stop_at::Integer) CSV.write(data_file_desktop, D) CSV.write(data_file_other, D) - return println("Wrote data to $(data_file_other).") + println("Wrote data to $(data_file_other).") end graphing_time(stop_at) diff --git a/examples/plot_random_core.jl b/examples/plot_random_core.jl index bd018cd..5163a12 100755 --- a/examples/plot_random_core.jl +++ b/examples/plot_random_core.jl @@ -11,7 +11,7 @@ function add_plot_info( factor2 = y > 1 ? 4 : 2.5 # plot!(annotations = (max(x * 2, x+100), (y - 10 * counter) / factor1, # text(extra, :left, 13))) - return annotate!(plt, max(x * 2, x + 100), ((y - 10 * counter) / factor1), extra) + annotate!(plt, max(x * 2, x + 100), ((y - 10 * counter) / factor1), extra) end function graphing( @@ -170,5 +170,5 @@ function graphing( end function graphing(q::Integer, n::Integer, d::Integer, stop_at::Integer; m::Integer = 10_000) - return graphing(q, n, d, obtain_data(q, n, d, stop_at; m = m), stop_at; m = m) + graphing(q, n, d, obtain_data(q, n, d, stop_at; m = m), stop_at; m = m) end diff --git a/src/abstract_types.jl b/src/abstract_types.jl index cfb77c4..c53d5de 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -36,7 +36,8 @@ mutable struct Word{N, T} Word(w::NTuple{N, T}) where {N, T} = new{N, T}(MVector{N, T}(w)) function Word(w::AbstractVector{T}) where {T} - return (len = length(w); new{len, T}(MVector{len, T}(w))) + len = length(w) + return new{len, T}(MVector{len, T}(w)) end Word(w::AbstractString) = MVector{length(w), eltype(w)}(collect(w)) Word(i::T...) where {T} = (len = length(i); new{len, T}(MVector{len, T}(i))) @@ -103,8 +104,8 @@ struct Alphabet{N} <: AbstractVector{Symbol} where {N} Σ::AbstractVector{Symbol} function Alphabet(Σ::Union{Vector{T}, String}) where {T} - return (Σ_unique = Set(Σ); - new{length(Σ_unique)}(ensure_symbolic(Σ_unique))) + Σ_unique = Set(Σ) + return new{length(Σ_unique)}(ensure_symbolic(Σ_unique)) end end # end struct diff --git a/src/algebra.jl b/src/algebra.jl index 95910ba..334db32 100644 --- a/src/algebra.jl +++ b/src/algebra.jl @@ -27,13 +27,13 @@ end ```julia mod(p::Polynomial, n::Int) -> Polynomial ``` - + Uses the `FinitePolynomial` constructor to return a polynomial `p` under modulus `n`. Parameters: - `p::Polynomial`: The input polynomial. - `n::Int`: The modulus of the field. - + Returns - Polynomial: A polynomial modulo n. """ @@ -43,13 +43,13 @@ Base.mod(p::Polynomial, n::Int) = FinitePolynomial(p, n).p ```julia Polynomial(A::Union{NTuple{N, T}, Vector{T}}, n::Int) -> Polynomial ``` - + Constructs a polynomial under modulo `n`. Parameters: - `A::Union{Tuple, AbstractArray}`: The polynomial coefficients. - `n::Int`: The modulus of the field. - + Returns - `Polynomial`: A polynomial modulo n. """ @@ -59,13 +59,13 @@ Polynomial(A::Union{NTuple{N, T}, Vector{T}}, n::Int) where {N, T} = mod(Polynom ```julia list_polys(n::Int, m::Int) -> Array ``` - + Lists all polynomials of degree less than to `n` under modulo `m`. Parameters: - `n::Int`: Highest degree of polynomial. - `m::Int`: The modulus of the field. - + Returns: - `Array`: An array of polynomials of degree less than n, under modulo m. """ @@ -78,13 +78,13 @@ end ```julia multiplication_table(degree::Int, modulo::Int) -> Matrix ``` - + Returns a table (matrix) of the multiplication of all combinations of polynomials for degree less than `degree`, under modulo `modulo`. Parameters: - `degree::Int`: Highest degree of polynomial. - `modulo::Int`: The modulus of the field. - + Returns: - `Matrix`: A multiplication table of all polynomials with degree less than n, under modulus. @@ -148,7 +148,7 @@ Parameters: - `v̲::Vector`: Another vector. - `...`: Other vectors. - `modulo::Int`: The modulus of the field. - + Returns: - `Array`: All vectors in the span of u̲ and v̲, under modulo. @@ -176,14 +176,14 @@ list_span(args...) = __list_span_inner(last(args), args[1:(end - 1)]...) ```julia islinear(C::Vector, modulo::Int; verbose::Bool = false) -> Bool ``` - + Determines whether a code `C` is a linear code (i.e., if it is closed under addition, scalar multiplication, and has the zero vector in it). Parameters: - `C::Vector`: A code, typically consisting of multiple vectors or strings. - `modulo::Int`: The modulus of the field under which you are working. - `verbose::Bool` (kwarg): print the point at which C fails, if it does. - + Returns: - `Bool`: Whether or not the code `C` is linear (true or false). @@ -235,13 +235,13 @@ end ```julia isirreducible(f::AbstractPolynomial, modulo::Int) -> Bool ``` - + Checks if a polynomial is irreducible. - + Parameters: - `f::Polynomial`: The polynomial you need to check. - `modulo::Int`: The modulus under which you are working. - + Returns: - `Bool`: Whether or not the polynomial is irreducible (true or false). @@ -276,7 +276,7 @@ Convert a matrix M into normal form under modulo n via Gauss-Jordan elimination. Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - + Returns: - `Matrix{Int}`: A matrix in normal form from Gauss-Jordan elimination. @@ -308,7 +308,7 @@ Convert a matrix M into normal form under modulo n via Gauss-Jordan elimination. Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - + Returns: - `Matrix{Int}`: A matrix in normal form from Gauss-Jordan elimination. @@ -340,7 +340,7 @@ Peforms Gauss-Jordan elimination on a matrix M, but allows for column swapping. Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - + Returns: - `Matrix{Int}`: A which represents an "equivalent" code to that of the matrix M. @@ -372,7 +372,7 @@ Peforms Gauss-Jordan elimination on a matrix M, but allows for column swapping. Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - + Returns: - `Matrix{Int}`: A which represents an "equivalent" code to that of the matrix M. @@ -404,12 +404,12 @@ Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - `colswap::Bool` (kwarg): A boolean flag indicating whether or not you allow for swapping of columns when constructing the generating matrix. - + Returns: - `Matrix{Int}`: A generating matrix. """ function generator!(M::AbstractArray{Int}, n::Int; colswap::Bool = false) - return ifelse(colswap, equivalent_code!(M, n), normal_form!(M, n)) + return colswap ? equivalent_code!(M, n) : normal_form!(M, n) end """ @@ -423,7 +423,7 @@ Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - `colswap::Bool` (kwarg): A boolean flag indicating whether or not you allow for swapping of columns when constructing the generating matrix. - + Returns: - `Matrix{Int}`: A generating matrix. """ @@ -435,13 +435,13 @@ end ```julia parity_check(M::AbstractArray{Int}, n::Int) -> Matrix{Int} ``` - + Constructs a parity check matrix. This is calculated from taking the non-identity part of a matrix in normal form (or equivalent — see `generator`), transposing it, multiplying it by negative one, and appending to it an appropriate sized identity matrix. - + Parameters: - `M::AbstractArray{Int}`: A matrix of Ints. - `n::Int`: The modulus of the finite field. - + Returns: - `Matrix{Int}`: A parity check matrix. """ @@ -457,16 +457,16 @@ end ```julia syndrome(v̲::Vector, Hᵀ::AbstractArray{Int}, n::Int) -> Matrix{Int} ``` - + Calculates the syndrome of a given word v̲ and a parity check matrix, transposed (Hᵀ), under modulo n. Parameters: - `v̲::Vector`: A word in the code. - `Hᵀ::AbstractArray{Int}`: The transpose of a parity check matrix. - + Returns: - `Vector`: The syndrome of a word in the code. - + --- ### Examples @@ -495,7 +495,7 @@ If the syndrome of a code is the zero vector, then the word used to calculate th Parameters: - `v̲::Vector`: A word. - `Hᵀ::AbstractArray{Int}`: The transpose of a parity check matrix. - + Returns: - `Bool`: If the word is in the code or not (true or false). diff --git a/src/bounds.jl b/src/bounds.jl index c7df3b4..6b65b75 100644 --- a/src/bounds.jl +++ b/src/bounds.jl @@ -274,8 +274,7 @@ function ishammingperfect(r::Int, q::Int) isequal(n, (q^r - 1) / (q - 1)) && \ isequal(d, 3) && \ - isequal(M, q^(((q^r - 1) / (q - 1)) - r)) && \ - return true + isequal(M, q^(((q^r - 1) / (q - 1)) - r)) && return true return false end diff --git a/src/messages.jl b/src/messages.jl index 3596983..137ef9d 100755 --- a/src/messages.jl +++ b/src/messages.jl @@ -162,37 +162,28 @@ function get_codewords_greedy(𝒰::UniverseParameters, d::Int) return C end -function get_codewords_greedy(Σ::Alphabet{N}, q::Int, n::Int, d::Int) where {N} - return get_codewords_greedy(UniverseParameters(Σ, q, n), d) -end -function get_codewords_greedy(Σ::Alphabet{N}, n::Int, d::Int) where {N} - return get_codewords_greedy(UniverseParameters(Σ, n), d) -end -function get_codewords_greedy(q::Int, n::Int, d::Int) - return get_codewords_greedy(UniverseParameters(q, n), d) -end -function get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int) - return get_codewords_greedy(Alphabet(Σ), q, n, d) -end -function get_codewords_greedy(Σ::AbstractArray, n::Int, d::Int) - return get_codewords_greedy(UniverseParameters(Σ, n), d) -end -function get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) - return get_codewords_greedy(Alphabet(Σ), q, n, d, 𝒰) -end - -function argmaxminima(A::AbstractArray; dims::Int) - return getindex(argmin(A; dims = dims), argmax(argmin(A; dims = dims))) -end -function maxminima(A::AbstractArray; dims::Int) - return getindex(minimum(A; dims = dims), maximum(minimum(A; dims = dims))) -end -function argminmaxima(A::AbstractArray; dims::Int) - return getindex(argmax(A; dims = dims), argmin(argmax(A; dims = dims))) -end -function minmaxima(A::AbstractArray; dims::Int) - return getindex(maximum(A; dims = dims), minimum(maximum(A; dims = dims))) -end +get_codewords_greedy(Σ::Alphabet{N}, q::Int, n::Int, d::Int) where {N} = + get_codewords_greedy(UniverseParameters(Σ, q, n), d) +get_codewords_greedy(Σ::Alphabet{N}, n::Int, d::Int) where {N} = + get_codewords_greedy(UniverseParameters(Σ, n), d) +get_codewords_greedy(q::Int, n::Int, d::Int) = + get_codewords_greedy(UniverseParameters(q, n), d) +get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int) = + get_codewords_greedy(Alphabet(Σ), q, n, d) +get_codewords_greedy(Σ::AbstractArray, n::Int, d::Int) = + get_codewords_greedy(UniverseParameters(Σ, n), d) +get_codewords_greedy(Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray) = + get_codewords_greedy(Alphabet(Σ), q, n, d, 𝒰) + +"TODO: need to document this" +argmaxminima(A::AbstractArray; dims::Int) = + getindex(argmin(A, dims = dims), argmax(argmin(A, dims = dims))) +maxminima(A::AbstractArray; dims::Int) = + getindex(minimum(A, dims = dims), maximum(minimum(A, dims = dims))) +argminmaxima(A::AbstractArray; dims::Int) = + getindex(argmax(A, dims = dims), argmin(argmax(A, dims = dims))) +minmaxima(A::AbstractArray; dims::Int) = + getindex(maximum(A, dims = dims), minimum(maximum(A, dims = dims))) """ ```julia @@ -223,77 +214,85 @@ Returns: - `Codewords{M}`: An array of codewords, each of length `M`. Each codewords is a tuple, and each character in said word is a symbol. # get a random word in the code start """ function get_codewords_random(𝒰::UniverseParameters, d::Int; m::Int = 1000) - C = eltype(𝒰)[] - - starting_word = rand(𝒰) # get a random word in the code start - push!(C, starting_word) - - for _ in 1:length(𝒰) - C′ = eltype(𝒰)[] - # while length(C′) < m - for _ in 1:m - wᵣ = rand(𝒰) - push_if_allowed!(C, C′, wᵣ, d) # if allowed in C, push to C′ - # wᵣ ∉ C′ && push_if_allowed!(C, C′, wᵣ, d) + out = eltype(𝒰)[] + for c in 𝒰.Σ + starting_word = ntuple(_ -> c, 𝒰.n) + C = eltype(𝒰)[] + function central_word(𝒰) + if isodd(length(𝒰.Σ)) + i = cld(length(𝒰.Σ), 2) + return ntuple(_ -> 𝒰.Σ[i], 𝒰.n) + end + l, u = fld(length(𝒰.Σ), 2), cld(length(𝒰.Σ), 2) + return ntuple(_ -> rand((𝒰.Σ[l], 𝒰.Σ[u])), 𝒰.n) + end + # starting_word = rand(𝒰) # get a random word in the code start + # starting_word = central_word(𝒰) + push!(C, starting_word) + + for _ in 1:length(𝒰) + C′ = eltype(𝒰)[] + # while length(C′) < m + for _ in 1:m + wᵣ = rand(𝒰) + push_if_allowed!(C, C′, wᵣ, d) # if allowed in C, push to C′ + # wᵣ ∉ C′ && push_if_allowed!(C, C′, wᵣ, d) + end + isempty(C′) && break + # [push_if_allowed!(C, C′, w, d) for _ in 1:m] + distances = Int[hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′] + # TODO: need to document this + best_word = getindex(C′, getindex(argmaxminima(distances, dims = 1), 2)) + push!(C, best_word) + end + println("$c: $(length(C))") + if length(out) < length(C) + out = copy(C) end - isempty(C′) && break - # [push_if_allowed!(C, C′, w, d) for _ in 1:m] - distances = Int[hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′] - best_word = getindex(C′, getindex(argmaxminima(distances; dims = 1), 2)) - push!(C, best_word) end - return C -end -function get_codewords_random( - Σ::Alphabet{N}, q::Int, n::Int, d::Int; m::Int = 1000 -) where {N} - return get_codewords_random(UniverseParameters(Σ, q, n), d; m = m) -end -function get_codewords_random(Σ::Alphabet{N}, n::Int, d::Int; m::Int = 1000) where {N} - return get_codewords_random(UniverseParameters(Σ, n), d; m = m) + return out end -function get_codewords_random(q::Int, n::Int, d::Int; m::Int = 1000) - return get_codewords_random(UniverseParameters(q, n), d; m = m) -end -function get_codewords_random(Σ::AbstractArray, q::Int, n::Int, d::Int; m::Int = 1000) - return get_codewords_random(Alphabet(Σ), q, n, d; m = m) -end -function get_codewords_random(Σ::AbstractArray, n::Int, d::Int; m::Int = 1000) - return get_codewords_random(UniverseParameters(Σ, n), d; m = m) -end -function get_codewords_random( +get_codewords_random(Σ::Alphabet{N}, q::Int, n::Int, d::Int; m::Int = 1000) where {N} = + get_codewords_random(UniverseParameters(Σ, q, n), d, m = m) +get_codewords_random(Σ::Alphabet{N}, n::Int, d::Int; m::Int = 1000) where {N} = + get_codewords_random(UniverseParameters(Σ, n), d, m = m) +get_codewords_random(q::Int, n::Int, d::Int; m::Int = 1000) = + get_codewords_random(UniverseParameters(q, n), d, m = m) +get_codewords_random(Σ::AbstractArray, q::Int, n::Int, d::Int; m::Int = 1000) = + get_codewords_random(Alphabet(Σ), q, n, d, m = m) +get_codewords_random(Σ::AbstractArray, n::Int, d::Int; m::Int = 1000) = + get_codewords_random(UniverseParameters(Σ, n), d, m = m) +get_codewords_random( Σ::AbstractArray, q::Int, n::Int, d::Int, 𝒰::AbstractArray; m::Int = 1000 -) - return get_codewords_random(Alphabet(Σ), q, n, d, 𝒰; m = m) -end +) = get_codewords_random(Alphabet(Σ), q, n, d, 𝒰, m = m) # using Mmap # function get_codewords_random_mmap(mmappath::AbstractString, 𝒰::UniverseParameters, d::Int) -# io = open(mmappath, "r+") # allow read and write -# # write(s, size(A,2)) -# # read(s, Int) -# # close(s) -# # B = Mmap.mmap(io, BitArray, (25,30000)) -# # Mmap.sync!(B); -# # close(io); -# # rm("mmap.bin") -# starting_word = rand(𝒰) # get a random word in the code start -# push!(C, starting_word) +# io = open(mmappath, "r+") # allow read and write +# # write(s, size(A,2)) +# # read(s, Int) +# # close(s) +# # B = Mmap.mmap(io, BitArray, (25,30000)) +# # Mmap.sync!(B); +# # close(io); +# # rm("mmap.bin") +# starting_word = rand(𝒰) # get a random word in the code start +# push!(C, starting_word) # -# for _ in 1:length(𝒰) -# C′ = Tuple[] -# for _ in 1:m -# push_if_allowed!(C, C′, rand(𝒰), d) # if allowed in C, push to C′ -# end -# isempty(C′) && break -# # [push_if_allowed!(C, C′, w, d) for _ in 1:m] -# distances = [hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′] -# best_word = getindex(C′, getindex(argmaxminima(distances, dims = 1), 2)) -# push!(C, best_word) -# end +# for _ in 1:length(𝒰) +# C′ = Tuple[] +# for _ in 1:m +# push_if_allowed!(C, C′, rand(𝒰), d) # if allowed in C, push to C′ +# end +# isempty(C′) && break +# # [push_if_allowed!(C, C′, w, d) for _ in 1:m] +# distances = [hamming_distance(wᵢ, wⱼ) for wᵢ in C, wⱼ in C′] +# best_word = getindex(C′, getindex(argmaxminima(distances, dims = 1), 2)) +# push!(C, best_word) +# end # -# return C +# return C # end # get_codewords_random(𝒰::UniverseParameters, d::Int) = get_codewords_random(joinpath(tempdir(), "mmap.bin"), 𝒰, d) @@ -453,9 +452,9 @@ function get_codewords(G::AbstractArray, m::Int) end # function obtain_maximal_code(𝒰::UniverseParameters, d::Int) -# adj_matrix = Matrix{Int8}(undef, length(𝒰), length(𝒰)) +# adj_matrix = Matrix{Int8}(undef, length(𝒰), length(𝒰)) # -# for u in CodeUniverseIterator(𝒰), u′ in CodeUniverseIterator(𝒰) -# distance = hamming_distance(u, u′) -# end +# for u in CodeUniverseIterator(𝒰), u′ in CodeUniverseIterator(𝒰) +# distance = hamming_distance(u, u′) +# end # end diff --git a/src/utils.jl b/src/utils.jl index f38e9cb..1398916 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -6,10 +6,10 @@ displaymatrix(M::AbstractArray) Displays a matrix `M` in a compact form from the terminal. """ function displaymatrix(M::AbstractArray) - return show( + show( IOContext(stdout, :limit => true, :compact => true, :short => true), "text/plain", M ) - return print("\n") + print("\n") end _Iterable{T} = Union{AbstractArray{T}, NTuple{N, T}} where {N}