From 6349f298ae723c21361f7450207b64f8e7f5e19c Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Mon, 29 Jan 2024 19:11:21 -0500 Subject: [PATCH] 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. --- engine-proto/engine.jl | 43 ++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/engine-proto/engine.jl b/engine-proto/engine.jl index 2f7294a..b282fdd 100644 --- a/engine-proto/engine.jl +++ b/engine-proto/engine.jl @@ -7,6 +7,26 @@ using LinearAlgebra using AbstractAlgebra 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 --- abstract type Element{T} end @@ -23,8 +43,6 @@ mutable struct Point{T} <: Element{T} ) where T = new(coords, vec, nothing) end -##coordnames(_::Point) = [:xₚ, :yₚ, :zₚ] - function buildvec!(pt::Point) coordring = parent(pt.coords[1]) 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) end -##coordnames(_::Sphere) = [:rₛ, :sₛ, :xₛ, :yₛ, :zₛ] - function buildvec!(sph::Sphere) coordring = parent(sph.coords[1]) sph.vec = sph.coords @@ -130,10 +146,6 @@ function realize(ctx::Construction{T}) where T end end - display(collect(elemenum)) - display(coordnamelist) - println() - # construct coordinate ring coordring, coordqueue = polynomial_ring(parent_type(T)(), coordnamelist, ordering = :degrevlex) @@ -150,16 +162,14 @@ function realize(ctx::Construction{T}) where T # construct coordinate vectors for (_, elem) in elemenum buildvec!(elem) - display(elem.coords) - display(elem.vec) - println() end # turn relations into equations - vcat( + eqns = vcat( equation.(ctx.relations), [elem.rel for elem in ctx.elements if !isnothing(elem.rel)] ) + Generic.Ideal(coordring, eqns) end end @@ -172,22 +182,23 @@ a = Engine.Point{CoeffType}() s = Engine.Sphere{CoeffType}() a_on_s = Engine.LiesOn{CoeffType}(a, 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_on_s = Engine.LiesOn{CoeffType}(b, s) Engine.push!(ctx, b) Engine.push!(ctx, 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] tangencies = [ Engine.AlignsWithBy{CoeffType}( spheres[n], spheres[mod1(n+1, length(spheres))], - -1//1 + CoeffType(-1//1) ) for n in 1:3 ] -ctx_chain = Engine.Construction{CoeffType}(elements = Set(spheres), relations = Set(tangencies)) \ No newline at end of file +ctx_chain = Engine.Construction{CoeffType}(elements = Set(spheres), relations = Set(tangencies)) +ideal_chain = Engine.realize(ctx_chain) \ No newline at end of file