diff --git a/src/CodingTheory.jl b/src/CodingTheory.jl index 31e717b..997e927 100755 --- a/src/CodingTheory.jl +++ b/src/CodingTheory.jl @@ -15,7 +15,8 @@ include("utils.jl") # Abstract types export FinitePolynomial, AbstractCode, NonStaticAbstractWord, AbstractWord, Word, - Alphabet, Messages, CodeUniverse, CodeUniverseIterator, UniverseParameters + Codewords, Alphabet, Messages, CodeUniverse, CodeUniverseIterator, + UniverseParameters export no_round, getindex, setindex!, firstindex, lastindex, size, length, rand, gensym, genalphabet, eltype, isword, isabstractword diff --git a/src/abstract_types.jl b/src/abstract_types.jl index 8d1ae5f..828e79d 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -15,14 +15,15 @@ abstract type FiniteField end abstract type AbstractCode end """ - NonStaticAbstractWord{N, T} = Union{NTuple{N, T}, AbstractVector{T}} where {N, T} + NonStaticAbstractWord{N, T} = Union{NTuple{N, T}, AbstractVector{T}, AbstractString} where {N, T} """ -NonStaticAbstractWord{N, T} = Union{NTuple{N, T}, AbstractVector{T}} where {N, T} +NonStaticAbstractWord{N, T} = Union{NTuple{N, T}, AbstractVector{T}, AbstractString} where {N, T} """ mutable struct Word{N, T} Word(w::NTuple{N, T}) Word(w::AbstractVector{T}) + Word(w::AbstractString) Word(i::T...) A Word is an `StaticArrays.MVector` which is efficient (like tuple) yet mutable. @@ -33,6 +34,8 @@ mutable struct Word{N, T} Word(w::NTuple{N, T}) where {N, T} = new{N, T}(MVector{N, T}(w)) Word(w::AbstractVector{T}) where {T} = (len = length(w); new{len, T}(MVector{len, T}(w))) + 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))) end @@ -57,6 +60,15 @@ isword(i...) = isword(i) isabstractword(w) = w isa AbstractWord isabstractword(i...) = isabstractword(i) +""" + Codewords{N} <: AbstractCode + +Simply a wrapper type for a vector of abstract words of length `N`. +""" +Codewords{N} = Vector{AbstractWord{N, T}} where T +# Codewords{N} = Vector{Word{N, T}} where T + + """ struct Alphabet <: AbstractCode @@ -177,9 +189,9 @@ struct CodeUniverseIterator <: AbstractCode return Iterators.product(Vector{eltype(Σ)}[Σ for _ in 1:𝒰.n]...) end - CodeUniverseIterator(Σ::Union{Alphabet, AbstractVector{T}}, q::Int, n::Int) where {T} = + CodeUniverseIterator(Σ::Union{Alphabet{N}, AbstractVector{T}}, q::Int, n::Int) where {N, T} = CodeUniverseIterator(UniverseParameters(Σ, q, n)) - CodeUniverseIterator(Σ::Union{Alphabet, AbstractVector{T}}, n::Int) where {T} = + CodeUniverseIterator(Σ::Union{Alphabet{N}, AbstractVector{T}}, n::Int) where {N, T} = CodeUniverseIterator(UniverseParameters(Σ, n)) CodeUniverseIterator(q::Int, n::Int) = CodeUniverseIterator(UniverseParameters(q, n)) @@ -195,12 +207,12 @@ Defines a structure for the messages in the code. Parameters are the abstract a An inner constructor function on the structure `CodeUniverse`. """ struct CodeUniverse <: AbstractCode - 𝒰::AbstractVector{Word{M, T}} where {M, T} + 𝒰::Codewords{M} where {M} Σ::Alphabet{N} where N q::Int # alphabet size n::Int # block length - function CodeUniverse(𝒰::AbstractVector{Word{N, T}}, Σ::Alphabet{N}) where {N, M, T} + function CodeUniverse(𝒰::Codewords{M}, Σ::Alphabet{N}) where {N, M} message_length_error = "We have fixed the block length of each message. Please ensure all messages are of equal length." _allequal_length_(𝒰) || throw(error(message_length_error)) diff --git a/src/distance.jl b/src/distance.jl index ecd5165..4afcd6a 100755 --- a/src/distance.jl +++ b/src/distance.jl @@ -17,7 +17,7 @@ Parameters: Returns: - Int: the number of changes needing to be made to one word for it to be identical to the other. """ -function hamming_distance(w₁::T, w₂::T) where T <: Union{String, Vector, NTuple} +function hamming_distance(w₁::T, w₂::T) where T <: AbstractWord if ! isequal(length(w₁), length(w₂)) throw(error("Cannot compute Hamming Distance on strings of unequal length.")) end @@ -33,7 +33,7 @@ function hamming_distance(w₁::T, w₂::T) where T <: Union{String, Vector, NTu return distance end -function __hamming_space(relation::Function, Σⁿ::AbstractArray{T}, w::AbstractArray, e::Int) where T +function __hamming_space(relation::Function, Σⁿ::AbstractArray{T}, w::AbstractArray, e::Int) where T <: AbstractWord e < 0 && throw(error("e (the ball/sphere \"radius\") must be a non-negative number.")) Σⁿ, w = deepsym(Σⁿ), ensure_symbolic(w) @@ -53,7 +53,7 @@ Parameters: Returns: - AbstractArray: The list of words in Σⁿ whose distance from w is less than or equal to e. Returns an array of array of symbols. """ -hamming_ball(Σⁿ::AbstractArray{T}, w::Vector{S}, e::Int) where {T, S} = +hamming_ball(Σⁿ::AbstractArray{T}, w::Vector{S}, e::Int) where {T <: AbstractWord, S} = __hamming_space(≤, Σⁿ, w, e) """ @@ -69,7 +69,7 @@ Parameters: Returns: - AbstractArray: The list of words in Σⁿ whose distance from w is exactly equal to e. Returns an array of array of symbols. """ -hamming_sphere(Σⁿ::AbstractArray{T}, w::Vector{S}, e::Int) where {T, S} = +hamming_sphere(Σⁿ::AbstractArray{T}, w::Vector{S}, e::Int) where {T <: AbstractWord, S} = __hamming_space(isequal, Σⁿ, w, e) """ @@ -83,7 +83,7 @@ Parameters: Return: - Int: the distance of the code. """ -function code_distance(C::AbstractArray{T}) where T +function code_distance(C::AbstractArray{T}) where T <: AbstractWord isempty(C) && return nothing C = deepsym(C) min_distance = nothing @@ -112,7 +112,7 @@ Parameters: Returns: - Int: The code distance after adding w to C. """ -function code_distance!(C::AbstractArray{T}, w::T) where T +function code_distance!(C::AbstractArray{T}, w::T) where T <: AbstractWord push!(C, w) return code_distance(C) end @@ -129,7 +129,7 @@ Parameters: Returns: - Int: The code distance after adding w to C. """ -function code_distance(C::AbstractArray{T}, w::T) where T +function code_distance(C::AbstractArray{T}, w::T) where T <: AbstractWord code_distance!(copy(C), w) end @@ -145,7 +145,7 @@ Parameters: Returns: - Bool: Yes, C can detect t errors, or no it cannot (true of false). """ -function t_error_detecting(C::AbstractArray{T}, t::Int) where T <: AbstractArray{Int} +function t_error_detecting(C::AbstractArray{T}, t::Int) where T <: Union{AbstractArray{Int}, AbstractWord} code_distance(C) ≥ t + 1 && return true return false end @@ -162,7 +162,7 @@ Parameters: Returns: - Bool: Yes, C can correct t errors, or no it cannot (true of false). """ -function t_error_correcting(C::AbstractArray{T}, t::Int) where T <: AbstractArray{Int} +function t_error_correcting(C::AbstractArray{T}, t::Int) where T <: Union{AbstractArray{Int}, AbstractWord} code_distance(C) ≥ 2*t + 1 && return true return false end @@ -180,7 +180,7 @@ Parameters: Returns: - Int: The maximum number t such that the code is t error detecting. """ -function find_error_detection_max(C::AbstractArray{T}, modulo::Int) where T <: AbstractArray{Int} +function find_error_detection_max(C::AbstractArray{T}, modulo::Int) where T <: Union{AbstractArray{Int}, AbstractWord} for t in (modulo - 1):-1:0 t_error_detecting(C, t) && return t end @@ -198,7 +198,7 @@ Parameters: Returns: - Int: The maximum number t such that the code is t error correcting. """ -function find_error_correction_max(C::AbstractArray{T}, modulo::Int) where T <: AbstractArray{Int} +function find_error_correction_max(C::AbstractArray{T}, modulo::Int) where T <: Union{AbstractArray{Int}, AbstractWord} for t in modulo-1:-1:0 t_error_correcting(C, t) && return t end