Skip to content

Commit

Permalink
truncate ideals, modules (#2660)
Browse files Browse the repository at this point in the history
* truncate ideals, modules

* adjust printing free resolution free module

* fix free-pres printing

---------

Co-authored-by: Claus Fieker <fieker@mathematik.uni-kl.de>
  • Loading branch information
wdecker and fieker authored Aug 11, 2023
1 parent eb8e61a commit 16a689f
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ direct_sum(M::ModuleFP{T}...; task::Symbol = :sum) where T
```@docs
direct_product(M::ModuleFP{T}...; task::Symbol = :prod) where T
```

## Truncation

```@docs
truncate(M::ModuleFP, g::GrpAbFinGenElem, task::Symbol = :with_morphism)
```
6 changes: 6 additions & 0 deletions docs/src/CommutativeAlgebra/ideals.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ saturation_with_index(I::MPolyIdeal{T}, J::MPolyIdeal{T}) where T
eliminate(I::MPolyIdeal{T}, V::Vector{T}) where T <: MPolyRingElem
```

### Truncation

```@docs
truncate(I::MPolyIdeal, g::GrpAbFinGenElem)
```

## Tests on Ideals

### Basic Tests
Expand Down
34 changes: 3 additions & 31 deletions src/Modules/ModuleTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -659,37 +659,9 @@ end
Base.getindex(FR::FreeResolution, i::Int) = FR.C[i]

function Base.show(io::IO, FR::FreeResolution)
C = FR.C
rk = Dict{Int, String}()
rng = reverse(Hecke.map_range(C))
len = 0

println(io, "")
print(io, "rank | ")
# get names
for i = rng
if i != first(rng)
rk[i] = "$(rank(C[i]))"
len += length(rk[i]) + 2
continue
end
end
for i = rng
if i != first(rng)
print(io, rk[i], " ")
end
end
println(io, "")
print(io, "-------|")
print(io, repeat("-", len))
println(io, "")
print(io, "degree | ")
for i = rng
if i != first(rng)
print(io, i, repeat(" ", length(rk[i]) + 1))
continue
end
end
C = FR.C
show(io, C)
return
end

mutable struct BettiTable
Expand Down
94 changes: 94 additions & 0 deletions src/Modules/ModulesGraded.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1926,3 +1926,97 @@ function hom(F::FreeMod_dec, G::FreeMod_dec)
set_attribute!(GH, :show => Hecke.show_hom, :hom => (F, G), :module_to_hom_map => to_hom_map)
return GH, to_hom_map
end

#############truncation#############

@doc raw"""
truncate(M::ModuleFP, g::GrpAbFinGenElem, task::Symbol = :with_morphism)
Given a finitely presented graded module `M` over a $\mathbb Z$-graded multivariate
polynomial ring with positive weights, return the truncation of `M` at degree `g`.
Put more precisely, return the truncation as an object of type `SubquoModule`.
Additionally, if `N` denotes this object,
- return the inclusion map `N` $\to$ `M` if `task = :with_morphism` (default),
- return and cache the inclusion map `N` $\to$ `M` if `task = :cache_morphism`,
- do none of the above if `task = :none`.
If `task = :only_morphism`, return only the inclusion map.
truncate(M::ModuleFP, d::Int, task::Symbol = :with_morphism)
Given a module `M` as above, and given an integer `d`, convert `d` into an element `g`
of the grading group of `base_ring(I)` and proceed as above.
# Examples
```jldoctest
julia> R, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = graded_free_module(R, 1)
Graded free module R^1([0]) of rank 1 over R
julia> V = [x*F[1]; y^4*F[1]; z^5*F[1]];
julia> M, _ = quo(F, V);
julia> M[1]
e[1]
julia> MT = truncate(M, 3);
julia> MT[1]
Graded subquotient of submodule of F generated by
1 -> z^3*e[1]
2 -> y*z^2*e[1]
3 -> y^2*z*e[1]
4 -> y^3*e[1]
5 -> x*z^2*e[1]
6 -> x*y*z*e[1]
7 -> x*y^2*e[1]
8 -> x^2*z*e[1]
9 -> x^2*y*e[1]
10 -> x^3*e[1]
by submodule of F generated by
1 -> x*e[1]
2 -> y^4*e[1]
3 -> z^5*e[1]
```
"""
function truncate(I::ModuleFP, g::GrpAbFinGenElem, task::Symbol = :with_morphism)
return truncate(I, Int(g[1]), task)
end

function truncate(I::ModuleFP, d::Int, task::Symbol = :with_morphism)
@req I isa FreeMod || I isa SubquoModule "Not implemented for the given type"
R = base_ring(I)
@req coefficient_ring(R) isa AbstractAlgebra.Field "The coefficient ring must be a field"
@req is_z_graded(R) "The base ring must be ZZ-graded"
W = R.d
W = [Int(W[i][1]) for i = 1:ngens(R)]
@req minimum(W) > 0 "The weights must be positive"
if is_zero(I)
return I
end
dmin = minimum(degree(Int, x) for x in gens(I))
if d <= dmin
return I
end
V = sort(gens(I), lt = (a, b) -> degree(Int, a) <= degree(Int, b))
RES = elem_type(I)[]
s = dmin
B = monomial_basis(R, d-s)
for i = 1:length(V)
if degree(Int, V[i]) < d
if degree(Int, V[i]) > s
s = degree(Int, V[i])
B = monomial_basis(R, d-s)
end
append!(RES, [x*V[i] for x in B])
else
push!(RES, V[i])
end
end
return sub(I, RES, task)
end
122 changes: 90 additions & 32 deletions src/Modules/UngradedModules.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4242,7 +4242,9 @@ function presentation(F::FreeMod)
Z = FreeMod(F.R, 0)
end
set_attribute!(Z, :name => "0")
return Hecke.ComplexOfMorphisms(ModuleFP, ModuleFPHom[hom(Z, F, Vector{elem_type(F)}()), hom(F, F, gens(F)), hom(F, Z, Vector{elem_type(Z)}([zero(Z) for i=1:ngens(F)]))], check = false, seed = -2)
M = Hecke.ComplexOfMorphisms(ModuleFP, ModuleFPHom[hom(Z, F, Vector{elem_type(F)}()), hom(F, F, gens(F)), hom(F, Z, Vector{elem_type(Z)}([zero(Z) for i=1:ngens(F)]))], check = false, seed = -2)
set_attribute!(M, :show => Hecke.pres_show)
return M
end

@doc raw"""
Expand All @@ -4260,13 +4262,8 @@ julia> B = R[x^2; y^3; z^4];
julia> M = SubquoModule(A, B);
julia> P = presentation(M);
julia> rank(P[1])
5
julia> rank(P[0])
2
julia> P = presentation(M)
0 <---- M <---- R^2 <---- R^5
```
```jldoctest
Expand All @@ -4279,7 +4276,7 @@ julia> Rg, (x, y, z) = grade(R, [Z[1],Z[1],Z[1]]);
julia> F = graded_free_module(Rg, [1,2,2]);
julia> p = presentation(F)
p_-2 <---- p_-1 <---- p_0 <---- p_1
0 <---- F <---- F <---- 0
julia> p[-2]
Graded free module Rg^0 of rank 0 over Rg
Expand Down Expand Up @@ -6147,6 +6144,74 @@ function map(FR::FreeResolution, i::Int)
return map(FR.C, i)
end

function free_show(io::IO, C::ComplexOfMorphisms)
Cn = get_attribute(C, :name)
if Cn === nothing
Cn = "F"
end

name_mod = String[]
rank_mod = Int[]

rng = range(C)
rng = first(rng):-1:0
arr = ("<--", "--")

R = Nemo.base_ring(C[first(rng)])
R_name = get_attribute(R, :name)
if R_name === nothing
R_name = AbstractAlgebra.find_name(R)
if R_name === nothing
R_name = "$R"
end
end

for i=reverse(rng)
M = C[i]
if get_attribute(M, :name) !== nothing
push!(name_mod, get_attribute(M, :name))
elseif AbstractAlgebra.find_name(M) !== nothing
push!(name_mod, AbstractAlgebra.find_name(M) )
else
push!(name_mod, "$R_name^$(rank(M))")
end
push!(rank_mod, rank(M))
end

io = IOContext(io, :compact => true)
N = get_attribute(C, :free_res)
if N !== nothing
print(io, "Free resolution")
print(io, " of ", N)
end
print(io, "\n")

pos = 0
pos_mod = Int[]

for i=1:length(name_mod)
print(io, name_mod[i])
push!(pos_mod, pos)
pos += length(name_mod[i])
if i < length(name_mod)
print(io, " ", arr[1], arr[2], " ")
pos += length(arr[1]) + length(arr[2]) + 2
end
end

print(io, "\n")
len = 0
for i=1:length(name_mod)
if i>1
print(io, " "^(pos_mod[i] - pos_mod[i-1]-len))
end
print(io, reverse(rng)[i])
len = length("$(reverse(rng)[i])")
end
# print(io, "\n")
end


@doc raw"""
free_resolution(F::FreeMod)
Expand All @@ -6156,7 +6221,7 @@ Return a free resolution of `F`.
"""
function free_resolution(F::FreeMod)
res = presentation(F)
set_attribute!(res, :show => Hecke.free_show, :free_res => F)
set_attribute!(res, :show => free_show, :free_res => F)
return FreeResolution(res)
end

Expand Down Expand Up @@ -6191,19 +6256,17 @@ by Submodule with 4 generators
4 -> z^4*e[1]
julia> fr = free_resolution(M, length=1)
rank | 2 6
-------|------
degree | 0 1
Free resolution of M
R^2 <---- R^6
0 1
julia> is_complete(fr)
false
julia> fr = free_resolution(M)
rank | 2 6 6 2 0
-------|---------------
degree | 0 1 2 3 4
Free resolution of M
R^2 <---- R^6 <---- R^6 <---- R^2 <---- 0
0 1 2 3 4
julia> is_complete(fr)
true
Expand Down Expand Up @@ -6336,10 +6399,9 @@ by Submodule with 4 generators
4 -> z^4*e[1]
julia> fr = free_resolution(M, length=1)
rank | 2 6
-------|------
degree | 0 1
Free resolution of M
R^2 <---- R^6
0 1
julia> is_complete(fr)
false
Expand All @@ -6348,19 +6410,15 @@ julia> fr[4]
Free module of rank 0 over Multivariate polynomial ring in 3 variables over QQ
julia> fr
rank | 2 6 6 2 0
-------|---------------
degree | 0 1 2 3 4
C_-2 <---- C_-1 <---- C_0 <---- C_1 <---- C_2 <---- C_3 <---- C_4
julia> is_complete(fr)
true
julia> fr = free_resolution(M, algorithm=:fres)
rank | 2 6 6 2 0
-------|---------------
degree | 0 1 2 3 4
Free resolution of M
R^2 <---- R^6 <---- R^6 <---- R^2 <---- 0
0 1 2 3 4
```
**Note:** Over rings other than polynomial rings, the method will default to a lazy,
Expand Down Expand Up @@ -6470,7 +6528,7 @@ function free_resolution(M::SubquoModule{<:MPolyRingElem};
cc = Hecke.ComplexOfMorphisms(Oscar.ModuleFP, maps, check = false, seed = -2)
cc.fill = _extend_free_resolution
cc.complete = cc_complete
set_attribute!(cc, :show => Hecke.free_show)
set_attribute!(cc, :show => free_show, :free_res => M)

return FreeResolution(cc)
end
Expand Down Expand Up @@ -6546,7 +6604,7 @@ function free_resolution_via_kernels(M::SubquoModule, limit::Int = -1)
insert!(mp, 1, g)
end
C = Hecke.ComplexOfMorphisms(ModuleFP, mp, check = false, seed = -2)
#set_attribute!(C, :show => Hecke.free_show, :free_res => M) # doesn't work
#set_attribute!(C, :show => free_show, :free_res => M) # doesn't work
return FreeResolution(C)
end

Expand Down
Loading

0 comments on commit 16a689f

Please sign in to comment.