Skip to content

Commit

Permalink
Slightly refine gaussian_elimination semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
Liozou committed Jul 5, 2022
1 parent 2c54e06 commit 1e63355
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 23 deletions.
36 changes: 21 additions & 15 deletions src/algorithms/rings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,19 @@ end
IterativeGaussianElimination(ring, sizehint=ring[1]) = IterativeGaussianEliminationNone(ring, sizehint)
IterativeGaussianElimination() = IterativeGaussianEliminationNone()

function _gaussian_elimination(gauss::IterativeGaussianElimination{T}, r::Vector{Int}) where T
"""
gaussian_elimination(gauss::IterativeGaussianElimination, r::Vector{Int})
Return `notindependent, info` where `notindependent` is `true` if `r` can be expressed as a
sum of vectors stored in `gauss`.
See [`PeriodicGraphs.gaussian_elimination!`](@ref) to store `r` in `gauss` if not, and for
more details dependending on the type of `gauss`.
Call `PeriodicGraphs.gaussian_elimination!(gauss, r, notindependent, info)` to obtain the
result of `PeriodicGraphs.gaussian_elimination!(gauss, r)` without duplicating computation.
"""
function gaussian_elimination(gauss::IterativeGaussianElimination{T}, r::Vector{Int}) where T
rings = gauss.rings
shortcuts = gauss.shortcuts
buffer1::Vector{Int} = gauss.buffer1
Expand All @@ -1212,7 +1224,7 @@ function _gaussian_elimination(gauss::IterativeGaussianElimination{T}, r::Vector
push!(track, idx)
end
symdiff_cycles!(buffer1, r, ridx)
isempty(buffer1) && return true, r1, maxlen, buffer1
isempty(buffer1) && return true, (r1, maxlen, buffer1)
r1 = buffer1[1]
idx = r1 > lenshort ? zero(Int32) : shortcuts[r1]
else
Expand All @@ -1226,24 +1238,15 @@ function _gaussian_elimination(gauss::IterativeGaussianElimination{T}, r::Vector
push!(track, idx)
end
symdiff_cycles!(buffer2, buffer1, ridx)
isempty(buffer2) && return true, r1, maxlen, buffer1
isempty(buffer2) && return true, (r1, maxlen, buffer1)
r1 = buffer2[1]
idx = r1 > lenshort ? zero(Int32) : shortcuts[r1]
buffer2, buffer1 = buffer1, buffer2
end

return false, r1, maxlen, buffer1
return false, (r1, maxlen, buffer1)
end

"""
gaussian_elimination(gauss::IterativeGaussianElimination, r::Vector{Int})
Test whether `r` can be expressed as a sum of vectors stored in `gauss`.
See [`PeriodicGraphs.gaussian_elimination!`](@ref) to store `r` in `gauss` if not, and for
more details dependending on the type of `gauss`.
"""
gaussian_elimination(gauss::IterativeGaussianElimination, r::Vector{Int}) = first(_gaussian_elimination(gauss, r))

# For an IterativeGaussianElimination of i rings of size at most l, symdiff_cycles cost at
# most (l + lenr) + (2l + lenr) + ... + (il + lenr) = O(i^2*l +i*lenr)
Expand All @@ -1267,6 +1270,11 @@ to obtain the sorted list of indices of such previously encountered vectors.
See also [`gaussian_elimination`](@ref) to test `r` without storing it.
"""
function gaussian_elimination!(gauss::IterativeGaussianElimination{T}, r::Vector{Int}) where T
notindependent, info = gaussian_elimination(gauss, r)
gaussian_elimination!(gauss, r, notindependent, info)
end

function gaussian_elimination!(gauss::IterativeGaussianElimination{T}, r::Vector{Int}, notindependent, (r1, maxlen, buffer1)) where T
rings = gauss.rings
shortcuts = gauss.shortcuts
if gauss isa IterativeGaussianEliminationLength
Expand All @@ -1275,8 +1283,6 @@ function gaussian_elimination!(gauss::IterativeGaussianElimination{T}, r::Vector
track::Vector{Int32} = first(gauss.track)
end

notindependent, r1, maxlen, buffer1 = _gaussian_elimination(gauss, r)

if notindependent
gauss isa IterativeGaussianEliminationLength && return maxlen < len
if gauss isa IterativeGaussianEliminationDecomposition
Expand Down
18 changes: 10 additions & 8 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -742,12 +742,13 @@ end
@test !PeriodicGraphs.gaussian_elimination!(gausslengths, [4, 7])
@test !PeriodicGraphs.gaussian_elimination!(gausslengths, [1, 3, 5])
@test length(gausslengths.track) == length(gausslengths.rings) == 4
@test PeriodicGraphs.gaussian_elimination(gausslengths, [1, 4, 5, 7])
@test first(PeriodicGraphs.gaussian_elimination(gausslengths, [1, 4, 5, 7]))
@test PeriodicGraphs.gaussian_elimination!(gausslengths, [1, 4, 5, 7])
@test length(gausslengths.track) == length(gausslengths.rings) == 4
@test !PeriodicGraphs.gaussian_elimination!(gausslengths, [3, 5, 6, 7])
@test !PeriodicGraphs.gaussian_elimination(gausslengths, [2, 3])
@test !PeriodicGraphs.gaussian_elimination!(gausslengths, [2, 3])
notindependent, info = PeriodicGraphs.gaussian_elimination(gausslengths, [2, 3])
@test !notindependent
@test !PeriodicGraphs.gaussian_elimination!(gausslengths, [2, 3], notindependent, info)
@test !PeriodicGraphs.gaussian_elimination!(gausslengths, [1, 2, 3])
@test length(gausslengths.track) == length(gausslengths.rings) == 7

Expand All @@ -756,11 +757,11 @@ end
@test !PeriodicGraphs.gaussian_elimination!(gaussnone, [4, 7])
@test !PeriodicGraphs.gaussian_elimination!(gaussnone, [1, 3, 5])
@test length(gaussnone.rings) == 4
@test PeriodicGraphs.gaussian_elimination(gaussnone, [1, 4, 5, 7])
@test first(PeriodicGraphs.gaussian_elimination(gaussnone, [1, 4, 5, 7]))
@test PeriodicGraphs.gaussian_elimination!(gaussnone, [1, 4, 5, 7])
@test !PeriodicGraphs.gaussian_elimination!(gaussnone, [3, 5, 6, 7])
@test !PeriodicGraphs.gaussian_elimination!(gaussnone, [2, 3])
@test !PeriodicGraphs.gaussian_elimination(gaussnone, [1, 2, 3])
@test !first(PeriodicGraphs.gaussian_elimination(gaussnone, [1, 2, 3]))
@test !PeriodicGraphs.gaussian_elimination!(gaussnone, [1, 2, 3])
@test PeriodicGraphs.gaussian_elimination!(gaussnone, [1, 2, 3])
@test gaussnone.shortcuts == Int32[4, 6, 1, 2, 5, 3, 7]
Expand All @@ -771,12 +772,13 @@ end
@test !PeriodicGraphs.gaussian_elimination!(gausstrack, [4, 7])
@test !PeriodicGraphs.gaussian_elimination!(gausstrack, [1, 3, 5])
@test length(gausstrack.rings) == 4
@test PeriodicGraphs.gaussian_elimination(gausstrack, [1, 4, 5, 7])
@test PeriodicGraphs.gaussian_elimination!(gausstrack, [1, 4, 5, 7])
notindependent, info = PeriodicGraphs.gaussian_elimination(gausstrack, [1, 4, 5, 7])
@test notindependent
@test PeriodicGraphs.gaussian_elimination!(gausstrack, [1, 4, 5, 7], notindependent, info)
@test PeriodicGraphs.retrieve_track!(gausstrack) == Int32[5, 4, 1]
@test !PeriodicGraphs.gaussian_elimination!(gausstrack, [3, 5, 6, 7])
@test !PeriodicGraphs.gaussian_elimination!(gausstrack, [2, 3])
@test !PeriodicGraphs.gaussian_elimination(gausstrack, [1, 2, 3])
@test !first(PeriodicGraphs.gaussian_elimination(gausstrack, [1, 2, 3]))
@test !PeriodicGraphs.gaussian_elimination!(gausstrack, [1, 2, 3])
@test PeriodicGraphs.gaussian_elimination!(gausstrack, [1, 2, 3])
@test PeriodicGraphs.retrieve_track!(gausstrack) == Int32[9, 8]
Expand Down

0 comments on commit 1e63355

Please sign in to comment.