Skip to content

Commit

Permalink
Move everything to appropriate places.
Browse files Browse the repository at this point in the history
  • Loading branch information
HechtiDerLachs committed Oct 3, 2023
1 parent 7947688 commit 4062c3b
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 183 deletions.
1 change: 0 additions & 1 deletion experimental/Experimental.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ include("Schemes/IdealSheaves.jl")
include("Schemes/AlgebraicCycles.jl")
include("Schemes/WeilDivisor.jl")
include("Schemes/CoveredProjectiveSchemes.jl")
include("Schemes/ExteriorPowers.jl")

include("Schemes/SimplifiedSpec.jl")
include("Schemes/CoherentSheaves.jl")
Expand Down
2 changes: 2 additions & 0 deletions src/Modules/ExteriorPowers/ExteriorPowers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include("Helpers.jl")
include("FreeModules.jl")
Original file line number Diff line number Diff line change
@@ -1,183 +1,3 @@
########################################################################
# Ordered multiindices of the form 0 < i₁ < i₂ < … < iₚ ≤ n.
#
# These provide a coherent way to enumerate the generators of an
# exterior power ⋀ ᵖ M of a module M given a chosen set of generators
# of M.
########################################################################
mutable struct OrderedMultiIndex{IntType<:IntegerUnion}
i::Vector{IntType}
n::IntType

function OrderedMultiIndex(i::Vector{T}, n::T) where {T<:IntegerUnion}
@assert all(k->i[k]<i[k+1], 1:length(i)-1) "indices must be strictly ordered"
return new{T}(i, n)
end
end

function ordered_multi_index(i::Vector{T}, n::T) where {T<:IntegerUnion}
return OrderedMultiIndex(i, n)
end

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns the vector (i₁,…,iₚ).
indices(a::OrderedMultiIndex) = copy(a.i)

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns n.
bound(a::OrderedMultiIndex) = a.n

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns p.
length(a::OrderedMultiIndex) = length(a.i)

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns iₖ.
getindex(a::OrderedMultiIndex, k::Int) = a.i[k]

index_type(a::OrderedMultiIndex) = index_type(typeof(a))
index_type(::Type{OrderedMultiIndex{T}}) where {T} = T

# Internal function for "multiplication" of ordered multiindices.
#
# The for i = (0 < i₁ < i₂ < … < iₚ ≤ n) and j = (0 < j₁ < j₂ < … < jᵣ ≤ n)
# the result is a pair `(sign, a)` with `sign` either 0 in case that
# iₖ = jₗ for some k and l, or ±1 depending on the number of transpositions
# needed to put (i₁, …, iₚ, j₁, …, jᵣ) into a strictly increasing order
# to produce `a`.
function _mult(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T}
@assert bound(a) == bound(b) "multiindices must have the same bounds"

# in case of a double index return zero
any(x->(x in indices(b)), indices(a)) && return 0, a

p = length(a)
q = length(b)
result_indices = vcat(indices(a), indices(b))
sign = 1

# bubble sort result_indices and keep track of the sign
for k in p:-1:1
l = k
c = result_indices[l]
while l < p + q && c > result_indices[l+1]
result_indices[l] = result_indices[l+1]
sign = -sign
l = l+1
end
result_indices[l] = c
end
return sign, result_indices
end

# For two ordered multiindices i = (0 < i₁ < i₂ < … < iₚ ≤ n)
# and j = (0 < j₁ < j₂ < … < jᵣ ≤ n) this returns a pair `(sign, a)`
# with `sign` either 0 in case that iₖ = jₗ for some k and l,
# or ±1 depending on the number of transpositions needed to put
# (i₁, …, iₚ, j₁, …, jᵣ) into a strictly increasing order to produce `a`.
function _wedge(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T}
sign, ind = _mult(a, b)
iszero(sign) && return sign, a
return sign, OrderedMultiIndex(ind, bound(a))
end

function _wedge(a::Vector{T}) where {T <: OrderedMultiIndex}
isempty(a) && error("list must not be empty")
isone(length(a)) && return 1, first(a)
k = div(length(a), 2)
b = a[1:k]
c = a[k+1:end]
sign_b, ind_b = _wedge(b)
sign_c, ind_c = _wedge(c)
sign, ind = _wedge(ind_b, ind_c)
return sign * sign_b * sign_c, ind
end

function ==(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T}
bound(a) == bound(b) || return false
return indices(a) == indices(b)
end

########################################################################
# A data type to facilitate iteration over all ordered multiindices
# of the form 0 < i₁ < i₂ < … < iₚ ≤ n for fixed 0 ≤ p ≤ n.
#
# Example:
#
# for i in OrderedMultiIndexSet(3, 5)
# # do something with i = (0 < i₁ < i₂ < i₃ ≤ 5).
# end
########################################################################
mutable struct OrderedMultiIndexSet
n::Int
p::Int

function OrderedMultiIndexSet(p::Int, n::Int)
@assert 0 <= p <= n "invalid bounds"
return new(n, p)
end
end

bound(I::OrderedMultiIndexSet) = I.n
index_length(I::OrderedMultiIndexSet) = I.p

Base.eltype(I::OrderedMultiIndexSet) = OrderedMultiIndex
Base.length(I::OrderedMultiIndexSet) = binomial(bound(I), index_length(I))

function Base.iterate(I::OrderedMultiIndexSet)
ind = OrderedMultiIndex([i for i in 1:index_length(I)], bound(I))
return ind, ind
end

function Base.iterate(I::OrderedMultiIndexSet, state::OrderedMultiIndex)
bound(I) == bound(state) || error("index not compatible with set")
ind = indices(state)
l = length(state)
while l > 0 && ind[l] == bound(I) - length(state) + l
l = l - 1
end
iszero(l) && return nothing
ind[l] = ind[l] + 1
l = l + 1
while l <= length(state)
ind[l] = ind[l-1] + 1
l = l + 1
end
result = OrderedMultiIndex(ind, bound(I))
return result, result
end

function Base.show(io::IO, ind::OrderedMultiIndex)
i = indices(ind)
print(io, "0 ")
for i in indices(ind)
print(io, "< $i ")
end
print(io, "<= $(bound(ind))")
end

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this
# returns the number k so that i appears at the k-th spot in the
# enumeration of all ordered multiindices for this pair 0 ≤ p ≤ n.
function linear_index(ind::OrderedMultiIndex)
n = bound(ind)
p = length(ind)
iszero(p) && return 1
isone(p) && return ind[1]
i = indices(ind)
return binomial(n, p) - binomial(n - first(i) + 1, p) + linear_index(OrderedMultiIndex(i[2:end].-first(i), n-first(i)))
end

# For a pair 0 ≤ p ≤ n return the k-th ordered multiindex in the
# enumeration of all ordered multiindices (0 < i₁ < i₂ < … < iₚ ≤ n).
function ordered_multi_index(k::Int, p::Int, n::Int)
(k < 1 || k > binomial(n, p)) && error("index out of range")
isone(p) && return OrderedMultiIndex([k], n)
i1 = 1
bin = binomial(n, p)
while !(bin - binomial(n - i1, p) > k - 1)
i1 = i1 + 1
end
prev_res = ordered_multi_index(k - bin + binomial(n - i1 + 1, p), p-1, n - i1)
return OrderedMultiIndex(pushfirst!(indices(prev_res).+i1, i1), n)
end

########################################################################
# Exterior powers of free modules
#
Expand Down Expand Up @@ -423,4 +243,3 @@ function induced_map_on_exterior_power(phi::FreeModuleHom{<:FreeMod, <:FreeMod,
return hom(Fp, Gp, img_gens)
end


180 changes: 180 additions & 0 deletions src/Modules/ExteriorPowers/Helpers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
########################################################################
# Ordered multiindices of the form 0 < i₁ < i₂ < … < iₚ ≤ n.
#
# These provide a coherent way to enumerate the generators of an
# exterior power ⋀ ᵖ M of a module M given a chosen set of generators
# of M.
########################################################################
mutable struct OrderedMultiIndex{IntType<:IntegerUnion}
i::Vector{IntType}
n::IntType

function OrderedMultiIndex(i::Vector{T}, n::T) where {T<:IntegerUnion}
@assert all(k->i[k]<i[k+1], 1:length(i)-1) "indices must be strictly ordered"
return new{T}(i, n)
end
end

function ordered_multi_index(i::Vector{T}, n::T) where {T<:IntegerUnion}
return OrderedMultiIndex(i, n)
end

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns the vector (i₁,…,iₚ).
indices(a::OrderedMultiIndex) = copy(a.i)

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns n.
bound(a::OrderedMultiIndex) = a.n

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns p.
length(a::OrderedMultiIndex) = length(a.i)

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this returns iₖ.
getindex(a::OrderedMultiIndex, k::Int) = a.i[k]

index_type(a::OrderedMultiIndex) = index_type(typeof(a))
index_type(::Type{OrderedMultiIndex{T}}) where {T} = T

# Internal function for "multiplication" of ordered multiindices.
#
# The for i = (0 < i₁ < i₂ < … < iₚ ≤ n) and j = (0 < j₁ < j₂ < … < jᵣ ≤ n)
# the result is a pair `(sign, a)` with `sign` either 0 in case that
# iₖ = jₗ for some k and l, or ±1 depending on the number of transpositions
# needed to put (i₁, …, iₚ, j₁, …, jᵣ) into a strictly increasing order
# to produce `a`.
function _mult(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T}
@assert bound(a) == bound(b) "multiindices must have the same bounds"

# in case of a double index return zero
any(x->(x in indices(b)), indices(a)) && return 0, a

p = length(a)
q = length(b)
result_indices = vcat(indices(a), indices(b))
sign = 1

# bubble sort result_indices and keep track of the sign
for k in p:-1:1
l = k
c = result_indices[l]
while l < p + q && c > result_indices[l+1]
result_indices[l] = result_indices[l+1]
sign = -sign
l = l+1
end
result_indices[l] = c
end
return sign, result_indices
end

# For two ordered multiindices i = (0 < i₁ < i₂ < … < iₚ ≤ n)
# and j = (0 < j₁ < j₂ < … < jᵣ ≤ n) this returns a pair `(sign, a)`
# with `sign` either 0 in case that iₖ = jₗ for some k and l,
# or ±1 depending on the number of transpositions needed to put
# (i₁, …, iₚ, j₁, …, jᵣ) into a strictly increasing order to produce `a`.
function _wedge(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T}
sign, ind = _mult(a, b)
iszero(sign) && return sign, a
return sign, OrderedMultiIndex(ind, bound(a))
end

function _wedge(a::Vector{T}) where {T <: OrderedMultiIndex}
isempty(a) && error("list must not be empty")
isone(length(a)) && return 1, first(a)
k = div(length(a), 2)
b = a[1:k]
c = a[k+1:end]
sign_b, ind_b = _wedge(b)
sign_c, ind_c = _wedge(c)
sign, ind = _wedge(ind_b, ind_c)
return sign * sign_b * sign_c, ind
end

function ==(a::OrderedMultiIndex{T}, b::OrderedMultiIndex{T}) where {T}
bound(a) == bound(b) || return false
return indices(a) == indices(b)
end

########################################################################
# A data type to facilitate iteration over all ordered multiindices
# of the form 0 < i₁ < i₂ < … < iₚ ≤ n for fixed 0 ≤ p ≤ n.
#
# Example:
#
# for i in OrderedMultiIndexSet(3, 5)
# # do something with i = (0 < i₁ < i₂ < i₃ ≤ 5).
# end
########################################################################
mutable struct OrderedMultiIndexSet
n::Int
p::Int

function OrderedMultiIndexSet(p::Int, n::Int)
@assert 0 <= p <= n "invalid bounds"
return new(n, p)
end
end

bound(I::OrderedMultiIndexSet) = I.n
index_length(I::OrderedMultiIndexSet) = I.p

Base.eltype(I::OrderedMultiIndexSet) = OrderedMultiIndex
Base.length(I::OrderedMultiIndexSet) = binomial(bound(I), index_length(I))

function Base.iterate(I::OrderedMultiIndexSet)
ind = OrderedMultiIndex([i for i in 1:index_length(I)], bound(I))
return ind, ind
end

function Base.iterate(I::OrderedMultiIndexSet, state::OrderedMultiIndex)
bound(I) == bound(state) || error("index not compatible with set")
ind = indices(state)
l = length(state)
while l > 0 && ind[l] == bound(I) - length(state) + l
l = l - 1
end
iszero(l) && return nothing
ind[l] = ind[l] + 1
l = l + 1
while l <= length(state)
ind[l] = ind[l-1] + 1
l = l + 1
end
result = OrderedMultiIndex(ind, bound(I))
return result, result
end

function Base.show(io::IO, ind::OrderedMultiIndex)
i = indices(ind)
print(io, "0 ")
for i in indices(ind)
print(io, "< $i ")
end
print(io, "<= $(bound(ind))")
end

# For an ordered multiindex i = (0 < i₁ < i₂ < … < iₚ ≤ n) this
# returns the number k so that i appears at the k-th spot in the
# enumeration of all ordered multiindices for this pair 0 ≤ p ≤ n.
function linear_index(ind::OrderedMultiIndex)
n = bound(ind)
p = length(ind)
iszero(p) && return 1
isone(p) && return ind[1]
i = indices(ind)
return binomial(n, p) - binomial(n - first(i) + 1, p) + linear_index(OrderedMultiIndex(i[2:end].-first(i), n-first(i)))
end

# For a pair 0 ≤ p ≤ n return the k-th ordered multiindex in the
# enumeration of all ordered multiindices (0 < i₁ < i₂ < … < iₚ ≤ n).
function ordered_multi_index(k::Int, p::Int, n::Int)
(k < 1 || k > binomial(n, p)) && error("index out of range")
isone(p) && return OrderedMultiIndex([k], n)
i1 = 1
bin = binomial(n, p)
while !(bin - binomial(n - i1, p) > k - 1)
i1 = i1 + 1
end
prev_res = ordered_multi_index(k - bin + binomial(n - i1 + 1, p), p-1, n - i1)
return OrderedMultiIndex(pushfirst!(indices(prev_res).+i1, i1), n)
end

1 change: 1 addition & 0 deletions src/Modules/Modules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ include("ModulesGraded.jl")
include("module-localizations.jl")
include("local_rings.jl")
include("mpolyquo.jl")
include("ExteriorPowers/ExteriorPowers.jl")

1 change: 0 additions & 1 deletion test/AlgebraicGeometry/Schemes/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,3 @@ include("AffineRationalPoint.jl")
include("ProjectiveRationalPoint.jl")
include("BlowupMorphism.jl")

include("ExteriorPowers.jl")
File renamed without changes.
1 change: 1 addition & 0 deletions test/Modules/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ include("local_rings.jl")
include("MPolyQuo.jl")
include("homological-algebra.jl")
include("ProjectiveModules.jl")
include("ExteriorPowers.jl")

0 comments on commit 4062c3b

Please sign in to comment.