Skip to content

Commit

Permalink
Add linear independence check to basis generation (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgoettgens authored Feb 26, 2024
1 parent 3d396ed commit ab3c1f0
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 14 deletions.
6 changes: 5 additions & 1 deletion src/DeformationBases/ArcDiagDeformBasis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ struct ArcDiagDeformBasis{C <: RingElem} <: DeformBasis{C}
iter = Iterators.flatten(iters)
if !no_normalize
iter = unique(Iterators.filter(b -> !iszero(b), iter))
len = length(iter)
collected = Vector{DeformationMap{C}}(collect(iter))
_, rels = is_linearly_independent_with_relations(coefficient_ring(sp), collected)
inds = [findlast(!iszero, vec(rels[i, :]))::Int for i in 1:nrows(rels)]
deleteat!(collected, inds)
return new{C}(length(collected), collected, extra_data, normalize)
end
return new{C}(len, iter, extra_data, normalize)
end
Expand Down
6 changes: 5 additions & 1 deletion src/DeformationBases/PseudographDeformBasis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ struct PseudographDeformBasis{C <: RingElem} <: DeformBasis{C}
iter = Iterators.flatten(iters)
if !no_normalize
iter = unique(Iterators.filter(b -> !iszero(b), iter))
len = length(iter)
collected = Vector{DeformationMap{C}}(collect(iter))
_, rels = is_linearly_independent_with_relations(coefficient_ring(sp), reverse(collected))
inds = [1 + ncols(rels) - (findfirst(!iszero, vec(rels[i, :]))::Int) for i in nrows(rels):-1:1]
deleteat!(collected, inds)
return new{C}(length(collected), collected, extra_data, normalize)
end
return new{C}(len, iter, extra_data, normalize)
end
Expand Down
100 changes: 100 additions & 0 deletions src/LinearIndependence.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const _linear_independence_rref_cutoff = 0

function column_rref!(mat::MatElem{T}) where {T <: FieldElem}
rk = rref!(AbstractAlgebra.Solve.lazy_transpose(mat))
return view(mat, :, 1:rk)
end

function column_rref!(mat::Nemo._MatTypes) # change to Nemo._FieldMatTypes
trmat = transpose!(mat)
rk = rref!(trmat)
return view(transpose!(trmat), :, 1:rk)
end

function is_linearly_independent(V::Vector{T}) where {T}
return is_linearly_independent_with_relations(V)[1]
end

function is_linearly_independent(F::Field, V::Vector{T}) where {T}
return is_linearly_independent_with_relations(F, V)[1]
end

function is_linearly_independent_with_relations(V::Vector{T}) where {T}
M = kernel(_linear_independence_coeff_matrix(V); side=:left)
return nrows(M) == 0, M
end

function is_linearly_independent_with_relations(F::Field, V::Vector{T}) where {T}
M = kernel(_linear_independence_coeff_matrix(F, V); side=:left)
return nrows(M) == 0, M
end

function _linear_independence_coeff_matrix(V::Vector{<:FieldElem})
@req length(V) > 0 "For empty vectors, the field needs to be specified"
return _linear_independence_coeff_matrix(parent(V[1]), V)
end

function _linear_independence_coeff_matrix(F::Field, V::Vector{<:FieldElem})
return matrix(F, length(V), 1, V)
end

function _linear_independence_coeff_matrix(F::Field, V::Vector{<:PolyRingElem})
@req isempty(V) || all(v -> parent(v) === parent(V[1]), V) "Incompatible polynomial rings"
return reduce(
hcat,
begin
mat = _linear_independence_coeff_matrix(F, [coeff(v, i) for v in V])
if ncols(mat) > _linear_independence_rref_cutoff * nrows(mat)
column_rref!(mat)
else
mat
end
end for i in 0:maximum(degree, V; init=-1);
init=zero_matrix(F, length(V), 0),
)
end

function _linear_independence_coeff_matrix(F::Field, V::Vector{<:MatElem})
n = length(V)
if n == 0
return zero_matrix(F, n, 0)
end
@req all(v -> parent(v) === parent(V[1]), V) "Incompatible matrix spaces"
return reduce(
hcat,
begin
mat = _linear_independence_coeff_matrix(F, [v[i] for v in V])
if ncols(mat) > _linear_independence_rref_cutoff * nrows(mat)
column_rref!(mat)
else
mat
end
end for i in eachindex(V[1]);
init=zero_matrix(F, n, 0),
)
end

function _linear_independence_coeff_matrix(F::Field, V::Vector{<:FreeAssAlgElem})
n = length(V)
if n == 0
return zero_matrix(F, n, 0)
end
R = parent(V[1])
C = base_ring(R)
@req all(v -> parent(v) === R, V) "Incompatible algebras"
coeff_maps = [Dict{Vector{Int}, elem_type(F)}(zip(exponent_words(v), coefficients(v))) for v in V]
support_words = reduce(union, keys.(coeff_maps))
return reduce(
hcat,
begin
mat = _linear_independence_coeff_matrix(F, [get(coeff_map, word, zero(C)) for coeff_map in coeff_maps])
if ncols(mat) > _linear_independence_rref_cutoff * nrows(mat)
column_rref!(mat)
else
mat
end
end for word in support_words;
init=zero_matrix(F, n, 0),
)
end

3 changes: 3 additions & 0 deletions src/PBWDeformations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ export general_linear_lie_algebra
export inneighbor
export inneighbors
export is_crossing_free
export is_linearly_independent
export is_linearly_independent_with_relations
export is_pbwdeformation
export isomorphic_module_with_simple_structure
export lookup_data
Expand Down Expand Up @@ -117,6 +119,7 @@ end

include("OscarPatches.jl")

include("LinearIndependence.jl")
include("ModuleSimpleStructure.jl")

include("DeformationBases/DeformBasis.jl")
Expand Down
18 changes: 6 additions & 12 deletions test/DeformationBases-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,12 @@
@test all_pbwdeformations(sp, b) == collect(b)

b = ArcDiagDeformBasis{QQFieldElem}(sp, 0:3)
@test length(collect(b)) == 4
@test all_pbwdeformations(sp, b; special_return=SMat)[1] ==
matrix(QQ, 4, 3, [1, 0, 0, 0, -3 // 2, 1 // 2, 0, 1, 0, 0, 0, 1])
@test length(collect(b)) == 3
@test all_pbwdeformations(sp, b; special_return=SMat)[1] == matrix(QQ, [1 0; 0 -3//2; 0 1])
ms = all_pbwdeformations(sp, b)
@test length(ms) == 3
@test length(ms) == 2
@test ms[1] == collect(b)[1]
@test 2 * ms[2] == -3 * collect(b)[2] + 2 * collect(b)[3]
@test 2 * ms[3] == 1 * collect(b)[2] + 2 * collect(b)[4]
@test iszero(ms[2] + ms[3]) # TODO: Check result for linear independence
end

@testset "SO_5, ⋀²V" begin
Expand Down Expand Up @@ -139,15 +136,12 @@
@test all_pbwdeformations(sp, b) == collect(b)

b = PseudographDeformBasis{QQFieldElem}(sp, 0:3)
@test length(collect(b)) == 4
@test all_pbwdeformations(sp, b; special_return=SMat)[1] ==
matrix(QQ, 4, 3, [1, 0, 0, 0, -3 // 2, 1 // 2, 0, 1, 0, 0, 0, 1])
@test length(collect(b)) == 3
@test all_pbwdeformations(sp, b; special_return=SMat)[1] == matrix(QQ, [1 0; 0 -3//2; 0 1])
ms = all_pbwdeformations(sp, b)
@test length(ms) == 3
@test length(ms) == 2
@test ms[1] == collect(b)[1]
@test 2 * ms[2] == -3 * collect(b)[2] + 2 * collect(b)[3]
@test 2 * ms[3] == 1 * collect(b)[2] + 2 * collect(b)[4]
@test iszero(ms[2] + ms[3])
end

@testset "SO_5, ⋀²V" begin
Expand Down

0 comments on commit ab3c1f0

Please sign in to comment.