Skip to content

Commit

Permalink
Updates AlgebraicSolving (#3987)
Browse files Browse the repository at this point in the history
Co-authored-by: Lars Göttgens <lars.goettgens@rwth-aachen.de>
  • Loading branch information
ederc and lgoettgens authored Sep 19, 2024
1 parent 90c2c88 commit e71c2b8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ cohomCalg_jll = "5558cf25-a90e-53b0-b813-cadaa3ae7ade"

[compat]
AbstractAlgebra = "0.42.5"
AlgebraicSolving = "0.5.1"
AlgebraicSolving = "0.7.0"
Distributed = "1.6"
GAP = "0.11.3"
Hecke = "0.33.0"
Expand Down
66 changes: 48 additions & 18 deletions src/Rings/groebner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ end
# standard basis for non-global orderings #############################
@doc raw"""
standard_basis(I::MPolyIdeal; ordering::MonomialOrdering = default_ordering(base_ring(I)),
complete_reduction::Bool = false, algorithm::Symbol = :buchberger)
complete_reduction::Bool = false, algorithm::Symbol = :buchberger)
Return a standard basis of `I` with respect to `ordering`.
Expand Down Expand Up @@ -151,7 +151,7 @@ with respect to the ordering
```
"""
function standard_basis(I::MPolyIdeal; ordering::MonomialOrdering = default_ordering(base_ring(I)),
complete_reduction::Bool = false, algorithm::Symbol = :buchberger)
complete_reduction::Bool = false, algorithm::Symbol = :buchberger)
complete_reduction && @assert is_global(ordering)
@req is_exact_type(elem_type(base_ring(I))) "This functionality is only supported over exact fields."
if haskey(I.gb, ordering) && (complete_reduction == false || I.gb[ordering].isReduced == true)
Expand Down Expand Up @@ -201,7 +201,9 @@ function standard_basis(I::MPolyIdeal; ordering::MonomialOrdering = default_orde
I.gb[ordering] = IdealGens(GB_dehom_gens, ordering, isGB = true)
end
elseif algorithm == :f4
groebner_basis_f4(I, complete_reduction=complete_reduction)
# since msolve v0.7.0 is most of the time more efficient
# to compute a reduced GB by default
groebner_basis_f4(I, complete_reduction=true)
end
return I.gb[ordering]
end
Expand Down Expand Up @@ -324,14 +326,22 @@ function standard_basis_highest_corner(I::MPolyIdeal; ordering::MonomialOrdering
return sb
end

function is_f4_applicable(I::MPolyIdeal, ordering::MonomialOrdering)
return (ordering == degrevlex(base_ring(I)) && !is_graded(base_ring(I))
&& ((coefficient_ring(I) isa FqField
&& absolute_degree(coefficient_ring(I)) == 1
&& characteristic(coefficient_ring(I)) < 2^31)
|| coefficient_ring(I) == QQ))
end

@doc raw"""
groebner_basis_f4(I::MPolyIdeal, <keyword arguments>)
Compute a Gröbner basis of `I` with respect to `degrevlex` using Faugère's F4 algorithm.
See [Fau99](@cite) for more information.
!!! note
At current state only prime fields of characteristic `0 < p < 2^{31}` are supported.
At current state only prime fields of characteristic `0 < p < 2^{31}` and the rationals are supported.
# Possible keyword arguments
- `initial_hts::Int=17`: initial hash table size `log_2`.
Expand All @@ -340,6 +350,8 @@ See [Fau99](@cite) for more information.
- `la_option::Int=2`: linear algebra option: exact sparse-dense (`1`), exact sparse (`2`, default), probabilistic sparse-dense (`42`), probabilistic sparse(`44`).
- `eliminate::Int=0`: size of first block of variables to be eliminated.
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`
- `normalize::Bool=true`: normalizes elements in computed Gröbner basis for `I`
- `truncate_lifting::Int=0`: degree up to which the elements of the Gröbner basis are lifted to `QQ`, `0` for complete lifting
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
# Examples
Expand Down Expand Up @@ -371,24 +383,35 @@ function groebner_basis_f4(
la_option::Int=2,
eliminate::Int=0,
complete_reduction::Bool=true,
normalize::Bool=true,
truncate_lifting::Int=0,
info_level::Int=0
)
AI = AlgebraicSolving.Ideal(I.gens.O)
AlgebraicSolving.groebner_basis(AI,
initial_hts = initial_hts,
nr_thrds = nr_thrds,
max_nr_pairs = max_nr_pairs,
la_option = la_option,
eliminate = eliminate,
complete_reduction = complete_reduction,
info_level = info_level)

AI = AlgebraicSolving.Ideal(I.gens.O)
vars = gens(base_ring(I))[eliminate+1:end]
ord = degrevlex(vars)
I.gb[ord] =
IdealGens(AI.gb[eliminate], ord, keep_ordering = false, isGB = true)
I.gb[ord].isReduced = complete_reduction

if length(AI.gens) == 0
I.gb[ord] = IdealGens(I.gens.Ox, singular_generators(I), complete_reduction)
I.gb[ord].ord = ord
I.gb[ord].isGB = true
I.gb[ord].S.isGB = true
else
AlgebraicSolving.groebner_basis(AI,
initial_hts = initial_hts,
nr_thrds = nr_thrds,
max_nr_pairs = max_nr_pairs,
la_option = la_option,
eliminate = eliminate,
complete_reduction = complete_reduction,
normalize = normalize,
truncate_lifting = truncate_lifting,
info_level = info_level)

I.gb[ord] =
IdealGens(AI.gb[eliminate], ord, keep_ordering = false, isGB = true)
I.gb[ord].isReduced = complete_reduction
end
return I.gb[ord]
end

Expand Down Expand Up @@ -1039,7 +1062,7 @@ end

function normal_form(A::Vector{T}, J::MPolyIdeal; ordering::MonomialOrdering=default_ordering(base_ring(J))) where { T <: MPolyRingElem }
@req is_exact_type(elem_type(base_ring(J))) "This functionality is only supported over exact fields."
if ordering == degrevlex(base_ring(J)) && typeof(base_ring(J)) == FqField && absolute_degree(base_ring(J)) == 1
if is_normal_form_f4_applicable(J, ordering)
res = _normal_form_f4(A, J)
else
res = _normal_form_singular(A, J, ordering)
Expand All @@ -1048,6 +1071,13 @@ function normal_form(A::Vector{T}, J::MPolyIdeal; ordering::MonomialOrdering=def
return res
end

function is_normal_form_f4_applicable(I::MPolyIdeal, ordering::MonomialOrdering)
return (ordering == degrevlex(base_ring(I)) && !is_graded(base_ring(I))
&& ((coefficient_ring(I) isa FqField
&& absolute_degree(coefficient_ring(I)) == 1
&& characteristic(coefficient_ring(I)) < 2^31)))
end

@doc raw"""
_normal_form_f4(A::Vector{T}, J::MPolyIdeal) where { T <: MPolyRingElem }
Expand Down
2 changes: 1 addition & 1 deletion test/Rings/groebner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ end
A = Oscar.IdealGens(R, [x*y-1, x^2+y^2])
@test_throws ErrorException Oscar._fglm(A, lex(R))
I = ideal(R, gens(A))
groebner_basis(I)
groebner_basis(I, algorithm=:buchberger)
@test_throws ErrorException Oscar._fglm(I.gb[degrevlex(R)], lex(R))
groebner_basis(I, complete_reduction=true)
G = Oscar._fglm(I.gb[degrevlex([x, y])], lex(R))
Expand Down
9 changes: 4 additions & 5 deletions test/Rings/solving.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@
@test res[2].denom == 2*x

# issue 1743
# disabled until fixed in msolve
#= R, (x1, x2) = polynomial_ring(QQ, ["x1", "x2"])
= I = ideal(R, [x1 + ZZRingElem(2)^100, x2 + ZZRingElem(2)^100])
= sols = Vector{QQFieldElem}[[-1267650600228229401496703205376, -1267650600228229401496703205376]]
= @test sols == real_solutions(I)[1] =#
R, (x1, x2) = polynomial_ring(QQ, ["x1", "x2"])
I = ideal(R, [x1 + ZZ(2)^100, x2 + ZZ(2)^100])
sols = Vector{QQFieldElem}[[-1267650600228229401496703205376, -1267650600228229401496703205376]]
@test sols == real_solutions(I)[1]
end

@testset "Rational solutions" begin
Expand Down

0 comments on commit e71c2b8

Please sign in to comment.