Extend AbstractAlgebra ideals to rational coefficients

The extension should also let us work over finite fields of prime order,
although we don't need to do that.
This commit is contained in:
Aaron Fenyes 2024-01-29 19:11:21 -05:00
parent 0731c7aac1
commit 6349f298ae
1 changed files with 27 additions and 16 deletions

View File

@ -7,6 +7,26 @@ using LinearAlgebra
using AbstractAlgebra using AbstractAlgebra
using Groebner using Groebner
# --- commutative algebra ---
# as of version 0.36.6, AbstractAlgebra only supports ideals in multivariate
# polynomial rings when coefficients are integers. in `reduce_gens`, the
# `lmnode` constructor requires < to be defined on the coefficients, and the
# `reducer_size` heuristic requires `ndigits` to be defined on the coefficients.
# this patch for `reducer_size` removes the `ndigits` dependency
##function Generic.reducer_size(f::T) where {U <: MPolyRingElem{<:FieldElement}, V, N, T <: Generic.lmnode{U, V, N}}
## if f.size != 0.0
## return f.size
## end
## return 0.0 + sum(j^2 for j in 1:length(f.poly))
##end
# as of version 0.36.6, AbstractAlgebra only supports ideals in multivariate
# polynomial rings when the coefficients are integers. we use Groebner to extend
# support to rationals and to finite fields of prime order
Generic.reduce_gens(I::Generic.Ideal{U}) where {T <: FieldElement, U <: MPolyRingElem{T}} =
Generic.Ideal{U}(base_ring(I), groebner(gens(I)))
# --- primitve elements --- # --- primitve elements ---
abstract type Element{T} end abstract type Element{T} end
@ -23,8 +43,6 @@ mutable struct Point{T} <: Element{T}
) where T = new(coords, vec, nothing) ) where T = new(coords, vec, nothing)
end end
##coordnames(_::Point) = [:xₚ, :yₚ, :zₚ]
function buildvec!(pt::Point) function buildvec!(pt::Point)
coordring = parent(pt.coords[1]) coordring = parent(pt.coords[1])
pt.vec = [one(coordring), dot(pt.coords, pt.coords), pt.coords...] pt.vec = [one(coordring), dot(pt.coords, pt.coords), pt.coords...]
@ -43,8 +61,6 @@ mutable struct Sphere{T} <: Element{T}
) where T = new(coords, vec, rel) ) where T = new(coords, vec, rel)
end end
##coordnames(_::Sphere) = [:rₛ, :sₛ, :xₛ, :yₛ, :zₛ]
function buildvec!(sph::Sphere) function buildvec!(sph::Sphere)
coordring = parent(sph.coords[1]) coordring = parent(sph.coords[1])
sph.vec = sph.coords sph.vec = sph.coords
@ -130,10 +146,6 @@ function realize(ctx::Construction{T}) where T
end end
end end
display(collect(elemenum))
display(coordnamelist)
println()
# construct coordinate ring # construct coordinate ring
coordring, coordqueue = polynomial_ring(parent_type(T)(), coordnamelist, ordering = :degrevlex) coordring, coordqueue = polynomial_ring(parent_type(T)(), coordnamelist, ordering = :degrevlex)
@ -150,16 +162,14 @@ function realize(ctx::Construction{T}) where T
# construct coordinate vectors # construct coordinate vectors
for (_, elem) in elemenum for (_, elem) in elemenum
buildvec!(elem) buildvec!(elem)
display(elem.coords)
display(elem.vec)
println()
end end
# turn relations into equations # turn relations into equations
vcat( eqns = vcat(
equation.(ctx.relations), equation.(ctx.relations),
[elem.rel for elem in ctx.elements if !isnothing(elem.rel)] [elem.rel for elem in ctx.elements if !isnothing(elem.rel)]
) )
Generic.Ideal(coordring, eqns)
end end
end end
@ -172,22 +182,23 @@ a = Engine.Point{CoeffType}()
s = Engine.Sphere{CoeffType}() s = Engine.Sphere{CoeffType}()
a_on_s = Engine.LiesOn{CoeffType}(a, s) a_on_s = Engine.LiesOn{CoeffType}(a, s)
ctx = Engine.Construction{CoeffType}(elements = Set([a]), relations= Set([a_on_s])) ctx = Engine.Construction{CoeffType}(elements = Set([a]), relations= Set([a_on_s]))
eqns_a_s = Engine.realize(ctx) ideal_a_s = Engine.realize(ctx)
b = Engine.Point{CoeffType}() b = Engine.Point{CoeffType}()
b_on_s = Engine.LiesOn{CoeffType}(b, s) b_on_s = Engine.LiesOn{CoeffType}(b, s)
Engine.push!(ctx, b) Engine.push!(ctx, b)
Engine.push!(ctx, s) Engine.push!(ctx, s)
Engine.push!(ctx, b_on_s) Engine.push!(ctx, b_on_s)
eqns_ab_s = Engine.realize(ctx) ideal_ab_s = Engine.realize(ctx)
spheres = [Engine.Sphere{CoeffType}() for _ in 1:3] spheres = [Engine.Sphere{CoeffType}() for _ in 1:3]
tangencies = [ tangencies = [
Engine.AlignsWithBy{CoeffType}( Engine.AlignsWithBy{CoeffType}(
spheres[n], spheres[n],
spheres[mod1(n+1, length(spheres))], spheres[mod1(n+1, length(spheres))],
-1//1 CoeffType(-1//1)
) )
for n in 1:3 for n in 1:3
] ]
ctx_chain = Engine.Construction{CoeffType}(elements = Set(spheres), relations = Set(tangencies)) ctx_chain = Engine.Construction{CoeffType}(elements = Set(spheres), relations = Set(tangencies))
ideal_chain = Engine.realize(ctx_chain)