Skip to content
Closed
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ GraphPlot = "0.6.0"
Graphs = "1.12.0"
Makie = "0.19.11"
NetworkLayout = "0.4.9"
Oscar = "1.2.2"
Oscar = "1.5.0"
StatsBase = "0.34.4"
WGLMakie = "0.8.15"
julia = "≥ 1.10"
Expand Down
2 changes: 1 addition & 1 deletion ext/MakieExt/LDPC/cycles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ enumerated. An empty figure and dictionary are returned when there are no cycles
already cached.
- Run `using Makie` to activate this extension.
"""
function CodingTheory.simple_cycle_length_distribution_plot(L::AbstractLDPCCode; len::Int = -1)
function CodingTheory.simple_cycle_length_distribution_plot(L::AbstractLDPCCode; len::Int = 16)
dist = simple_cycle_length_distribution(L, len = len)
x_data = collect(keys(dist))
y_data = collect(values(dist))
Expand Down
36 changes: 36 additions & 0 deletions src/Classical/cyclic_code.jl
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,42 @@ function _generator_matrix(F::FqField, n::Int, k::Int, g::FqPolyRingElem)
return G
end

function _classify_factors(poly::fpPolyRingElem)
# the problem with reverse(poly) == poly is that coefficents(poly) is not a fixed size
n = degree(poly)
F = base_ring(parent(poly))
F0 = F(0)
facs = [x[1] for x in collect(factor(poly))]
self_reciprocal_facs = Vector{fpPolyRingElem}()
pairs = Vector{Tuple{fpPolyRingElem, fpPolyRingElem}}()
temp = zeros(F, 1, n + 1)
temp2 = zeros(F, 1, n + 1)
for f in facs
f_coeffs = collect(coefficients(f))
temp[1, end - length(f_coeffs) + 1:end] .= reverse(f_coeffs)
temp2[1, end - length(f_coeffs) + 1:end] .= f_coeffs
if temp == temp2
push!(self_reciprocal_facs, f)
else
for f2 in facs
if f != f2
f_coeffs = collect(coefficients(f2))
temp2[1, 1:end - length(f_coeffs)] .= F0
temp2[1, end - length(f_coeffs) + 1:end] .= f_coeffs
if temp == temp2
push!(pairs, (f, f2))
break
end
end
end
end
temp[1, :] .= F0
temp2[1, :] .= F0
end

return self_reciprocal_facs, pairs
end

# TODO: make flat optional throughout
"""
defining_set(nums::Vector{Int}, q::Int, n::Int, flat::Bool = true)
Expand Down
2 changes: 1 addition & 1 deletion src/Classical/linear_code.jl
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ function _are_perm_equivalent_exhaustive_search(C1::AbstractLinearCode, C2::Abst
sym = symmetric_group(nc)
for e in collect(sym)
P = permutation_matrix(C1.F, e)
if G1 * P == G2
if G1 * P == G2
return (true, P)
end
end
Expand Down
105 changes: 66 additions & 39 deletions src/Classical/weight_dist.jl

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions src/CodingTheory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ const CTPolyRingElem = PolyRingElem{<:CTFieldElem}
const CTGroupAlgebra = GroupAlgebraElem{fpFieldElem, GroupAlgebra{fpFieldElem, FinGenAbGroup, FinGenAbGroupElem}}
const CTChainComplex = Union{ComplexOfMorphisms{AbstractAlgebra.FPModule{fpFieldElem}}} # residue and group algebras later
const CTPolyMatrix = Union{AbstractAlgebra.Generic.MatSpaceElem{fpPolyRingElem}, AbstractAlgebra.Generic.MatSpaceElem{FqPolyRingElem}}
const CTLRPolyElem = AbstractAlgebra.Generic.LaurentMPolyWrap{fpFieldElem, fpMPolyRingElem,
AbstractAlgebra.Generic.LaurentMPolyWrapRing{fpFieldElem, fpMPolyRing}}

include("Classical/types.jl")
export AbstractCode, AbstractNonadditiveCode, AbstractNonlinearCode, AbstractAdditiveCode,
Expand All @@ -72,7 +74,8 @@ include("Quantum/types.jl")
export AbstractSubsystemCode, AbstractSubsystemCodeCSS, AbstractStabilizerCode, AbstractStabilizerCodeCSS,
AbstractGraphStateSubsystem, AbstractGraphStateSubsystemCSS, AbstractGraphStateStabilizer,
AbstractGraphStateStabilizerCSS, AbstractHypergraphProductCode, AbstractEASubsystemCode,
AbstractEASubsystemCodeCSS, AbstractEAStabilizerCode, AbstractEAStabilizerCodeCSS
AbstractEASubsystemCodeCSS, AbstractEAStabilizerCode, AbstractEAStabilizerCodeCSS, AbstractGeneralizedToricCode

# misc
export LogicalTrait, GaugeTrait, CSSTrait, HasLogicals, HasNoLogicals, HasGauges, HasNoGauges,
IsCSS, IsNotCSS, copy, ChainComplex
Expand All @@ -95,7 +98,7 @@ export kronecker_product, Hamming_weight, weight, wt, Hamming_distance, distance
is_valid_bipartition, extract_bipartition, is_Hermitian_self_orthogonal,
row_supports, row_supports_symplectic, strongly_lower_triangular_reduction,
residue_polynomial_to_circulant_matrix, group_algebra_element_to_circulant_matrix,
load_alist, extended_binomial
load_alist, extended_binomial, mult_order, prepare_mult_order
# load_alist, _rref_non_pivot_cols
# , _min_wt_row
# , circ_shift
Expand Down Expand Up @@ -473,4 +476,12 @@ export copying, gauging, thickening_and_choose_heights, coning, quantum_weight_r
include("Quantum/homological_measurements.jl")
export homological_measurement, Cheeger_constant

#############################
# Quantum/GeneralizedToricCode.jl
#############################

include("Quantum/GeneralizedToricCode.jl")
export GeneralizedToricCode, FiniteGeneralizedToricCode, maximum_dimension,
Laurent_polynomial_ring, defining_polynomials, twist_vectors

end
12 changes: 6 additions & 6 deletions src/LDPC/MP_decoders.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1139,12 +1139,12 @@ function _message_passing_fast(H_Int::Matrix{UInt8}, v::Matrix{UInt8}, syndrome_
current_bits[i] = var_to_check_messages[i, curr_iter] >= 0 ? 0 : 1
end

LinearAlgebra.mul!(syn, H_Int, current_bits)
if syndrome_based
all(syn[i] % 2 == v[i, 1] for i in 1:num_check) && return true, current_bits, iter, var_to_check_messages[:, curr_iter]
else
all(iszero(syn[i] % 2) for i in 1:num_check) && return true, current_bits, iter, var_to_check_messages[:, curr_iter]
end
# LinearAlgebra.mul!(syn, H_Int, current_bits)
# if syndrome_based
# all(syn[i] % 2 == v[i, 1] for i in 1:num_check) && return true, current_bits, iter, var_to_check_messages[:, curr_iter]
# else
# all(iszero(syn[i] % 2) for i in 1:num_check) && return true, current_bits, iter, var_to_check_messages[:, curr_iter]
# end

if schedule == :parallel
temp_iter = curr_iter
Expand Down
2 changes: 1 addition & 1 deletion src/LDPC/cycles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ is returned when there is no cycles.
columns of `parity_check_matrix(L)` then top-to-bottom by rows.
"""
function enumerate_simple_cycles(L::AbstractLDPCCode; len::Int = 16)
ispositive(len) || throw(DomainError("Cycle length parameter must be a positive integer"))
is_positive(len) || throw(DomainError("Cycle length parameter must be a positive integer"))

# TODO add this variable to struct
if len > L.max_cyc_len
Expand Down
9 changes: 9 additions & 0 deletions src/Lattices/Voronoi.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2025 David Marquis
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

#############################
# general functions
#############################
232 changes: 232 additions & 0 deletions src/Lattices/lattices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# Copyright (c) 2025 Eric Sabo, David Marquis
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

#############################
# constructors
#############################

# TODO do we even want to accept a Gram matrix here?
"""
Lattice(B::MatrixElem{<:RingElem}; type::Symbol = :basis)

Return a lattice using the columns of `B` as a basis.
"""
function Lattice(B::MatrixElem{<:RingElem}; type::Symbol = :basis)
if type == :basis
rank(B) == ncols(B) || throw(ArgumentError("Basis must have full column rank."))
return Lattice(B)
elseif type == :Gram
# which decomp to use here?

return Lattice(B)
else
throw(ArgumentError("Parameter `type` must be either `:basis` or `:Gram`."))
end
end

"""
Lattice(V::Vector{MatrixElem{<:RingElem}})

Return a lattice using the elements of the vectors as a basis.
"""
function Lattice(V::Vector{MatrixElem{<:RingElem}})
# check equal sizes and base rings
# stack rows into columns of matrix

rank(B) == ncols(B) || throw(ArgumentError("Basis must have full column rank."))
return Lattice(B)
end

"""


"""
function Lattice(G::MatrixElem{<:RingElem})


return Lattice(B)
end

"""
construction_A(C::AbstractLinearCode)

Return the lattice given by applying Construction A to the code `C`.
"""
function construction_A(C::AbstractLinearCode)


end

"""
construction_B(C::AbstractLinearCode)

Return the lattice given by applying Construction B to the code `C`.
"""
function construction_B(C::AbstractLinearCode)


end

"""
construction_C(C::AbstractLinearCode)

Return the lattice given by applying Construction C to the code `C`.
"""
function construction_C(C::AbstractLinearCode)


end

#############################
# getter functions
#############################

"""
basis(L::Lattice)

Return the basis of the lattice.
"""
basis(L::Lattice) = L.B

"""
rank(L::Lattice)

Return the rank of the lattice.
"""
rank(L::Lattice) = size(L.B, 1)

"""
dimension(L::Lattice)
dim(L::Lattice)

Return the dimension of the lattice.
"""
dimension(L::Lattice) = size(L.B, 2)
dim(L::Lattice) = dimension(L)

"""
is_full_rank(L::Lattice)

Return `true` if the lattice is full rank; otherwise return `false`.
"""
is_full_rank(L::Lattice) = dimension(L) == rank(L)

"""
discriminant(L::Lattice)
disc(L::Lattice)

Return the discriminant of the lattice.
"""
discriminant(L::Lattice) = det(Gram_matrix(L))
disc(L::Lattice) = discriminant(L)

"""
Gram_matrix(L::Lattice)

Return the Gram matrix of the basis of the lattice.
"""
Gram_matrix(L::Lattice) = gram(L.B)

"""
volume(L::Lattice)
vol(L::Lattice)
determinate(L::Lattice)
det(L::Lattice)

Return the volumne of the lattice.
"""
volume(L::Lattice) = sqrt(disc(L))
vol(L::Lattice) = volume(L)
determinate(L::Lattice) = volume(L)
det(L::Lattice) = volume(L)

"""
check_matrix(L::Lattice)

Return the check matrix of the lattice.
"""
check_matrix(L::Lattice) = inverse(L.B)

"""
shortest_vector(L::Lattice)

"""
shortest_vector(L::Lattice)

"""
successive_minima(L::Lattice)

"""
successive_minima(L::Lattice)

"""
dual_basis(L::Lattice)

Return a dual basis for the lattice.
"""
function dual_basis(L::Lattice)
Ginv = inverse(Gram_matrix(L))
new_basis = Ginv * B
# b^*_i = \sum_j (G_inv)_ij b_j
return new_basis
end

"""
dual(L::Lattice)

Return the dual lattice.
"""
dual(L::Lattice) = Lattice(dual_basis(L))

"""
is_unimodular(L::Lattice)

Return `true` if the lattie is unimodular; otherwise return `false`.
"""
function is_unimodular(L::Lattice)
# Gram matrix has integer entries and disc(L) == 1
end

#############################
# general functions
#############################

"""


"""
function in(v::MatrixElem{<:RingElem}, L::Lattice)
# check sizes and rings
# setup Bx = v
# true if solution exists and is in ZZ
end

function is_sublattice(L1::Lattice, L2::Lattice)

end

function is_equal(L1::Lattice, L2::Lattice)
# L1 ⊆ L2 && L2 ⊆ L1

end

"""


"""
function coding_gain(L::Lattice)

end

"""


"""
function covering_radius(L::Lattice)

end

# SVP, CVP
5 changes: 5 additions & 0 deletions src/Lattices/misc_known_lattices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) 2025 David Marquis
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
Loading
Loading