Skip to content

Commit 5e649f2

Browse files
authored
Merge pull request #26 from ederc/normal-form
Adds normal form interface for msolve -> prepares v0.4.0
2 parents 9b6f3ec + e335e42 commit 5e649f2

File tree

15 files changed

+245
-18
lines changed

15 files changed

+245
-18
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "AlgebraicSolving"
22
uuid = "66b61cbe-0446-4d5d-9090-1ff510639f9d"
33
authors = ["ederc <[email protected]>", "Mohab Safey El Din <[email protected]", "Rafael Mohr <[email protected]>"]
4-
version = "0.3.7"
4+
version = "0.4.0"
55

66
[deps]
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
@@ -20,4 +20,4 @@ LoopVectorization = "0.12"
2020
Nemo = "0.35.1, 0.36, 0.37"
2121
StaticArrays = "1"
2222
julia = "1.6"
23-
msolve_jll = "0.4.6"
23+
msolve_jll = "0.6.1"

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a"
88

99
[compat]
1010
Documenter = "0.26"
11-
msolve_jll = "0.4.1"
11+
msolve_jll = "0.6.1"
1212
Nemo = "0.35.1"

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ makedocs(
2020
"index.md",
2121
"types.md",
2222
"Algorithms" => ["groebner-bases.md",
23+
"normal-forms.md",
2324
"solvers.md"],
2425
"Examples" => "katsura.md"
2526
]

docs/src/groebner-bases.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,5 @@ variables of the first block via the `eliminate` parameter in the
6161
To compute signature Gröbner bases use
6262

6363
```@docs
64-
sig_groebner_basis(
65-
sys::Vector{T} where T <: MPolyElem,
66-
info_level::Int=0,
67-
degbound::Int=0
68-
)
64+
sig_groebner_basis(sys::Vector{T}; info_level::Int = 0, degbound::Int = 0) where {T <: MPolyRingElem}
6965
```

docs/src/normal-forms.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
```@meta
2+
CurrentModule = AlgebraicSolving
3+
DocTestSetup = quote
4+
using AlgebraicSolving
5+
end
6+
```
7+
8+
```@setup algebraicsolving
9+
using AlgebraicSolving
10+
```
11+
12+
```@contents
13+
Pages = ["normal-forms.md"]
14+
```
15+
16+
# Gröbner bases
17+
18+
## Introduction
19+
20+
AlgebraicSolving allows to compute normal forms of a polynomial resp. a finite
21+
array of polynomials w.r.t. some given ideal over a finite field of
22+
characteristic smaller $2^{31}$ w.r.t. the degree reverse lexicographical
23+
monomial order.
24+
25+
**Note:** It therefore might first compute a Gröbner bases for the ideal.
26+
## Functionality
27+
28+
```@docs
29+
normal_form(
30+
f::T,
31+
I::Ideal{T};
32+
nr_thrds::Int=1,
33+
info_level::Int=0
34+
) where T <: MPolyRingElem
35+
```
36+
37+
```@docs
38+
normal_form(
39+
F::Vector{T},
40+
I::Ideal{T};
41+
nr_thrds::Int=1,
42+
info_level::Int=0
43+
) where T <: MPolyRingElem
44+
```

src/AlgebraicSolving.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include("types.jl")
1010
#= functionality =#
1111
include("interfaces/nemo.jl")
1212
include("algorithms/groebner-bases.jl")
13+
include("algorithms/normal-forms.jl")
1314
include("algorithms/solvers.jl")
1415
#= siggb =#
1516
include("siggb/siggb.jl")

src/algorithms/groebner-bases.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ function _core_groebner_basis(
151151
gb_exp = Ref(Ptr{Cint}(0))
152152
gb_cf = Ref(Ptr{Cvoid}(0))
153153

154-
nr_terms = ccall((:f4_julia, libneogb), Int,
154+
nr_terms = ccall((:export_f4, libneogb), Int,
155155
(Ptr{Nothing}, Ptr{Cint}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
156156
Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Cint, Cint, Cint, Cint, Cint, Cint,
157157
Cint, Cint, Cint, Cint, Cint, Cint, Cint),
@@ -166,7 +166,7 @@ function _core_groebner_basis(
166166
ptr = reinterpret(Ptr{Int32}, gb_cf[])
167167
jl_cf = Base.unsafe_wrap(Array, ptr, nr_terms)
168168

169-
basis = _convert_finite_field_gb_to_abstract_algebra(
169+
basis = _convert_finite_field_array_to_abstract_algebra(
170170
jl_ld, jl_len, jl_cf, jl_exp, R, eliminate)
171171

172172

src/algorithms/normal-forms.jl

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import msolve_jll: libneogb
2+
3+
export normal_form
4+
5+
@doc Markdown.doc"""
6+
normal_form(
7+
f::T,
8+
I::Ideal{T};
9+
nr_thrds::Int=1,
10+
info_level::Int=0
11+
) where T <: MPolyRingElem
12+
13+
Compute the normal forms of the elements of `F` w.r.t. a degree reverse
14+
lexicographical Gröbner basis of `I`.
15+
16+
**Note:** If `I` has not already cached a degree reverse lexicographical
17+
Gröbner basis, then this one is first computed.
18+
19+
# Arguments
20+
- `F::Vector{T} where T <: MPolyRingElem`: elements to be reduced.
21+
- `I::Ideal{T} where T <: MPolyRingElem`: ideal data to reduce with.
22+
- `nr_thrds::Int=1`: number of threads for parallel linear algebra.
23+
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
24+
25+
# Examples
26+
```jldoctest
27+
julia> using AlgebraicSolving
28+
29+
julia> R, (x,y) = polynomial_ring(GF(101),["x","y"])
30+
(Multivariate polynomial ring in 2 variables over GF(101), fpMPolyRingElem[x, y])
31+
32+
julia> I = Ideal([y*x^3+12-y, x+y])
33+
fpMPolyRingElem[x^3*y + 100*y + 12, x + y]
34+
35+
julia> f = 2*x^2+7*x*y
36+
2*x^2 + 7*x*y
37+
38+
julia> normal_form(f, I)
39+
96*y^2
40+
```
41+
"""
42+
function normal_form(
43+
f::T,
44+
I::Ideal{T};
45+
nr_thrds::Int=1,
46+
info_level::Int=0
47+
) where T <: MPolyRingElem
48+
nf = _core_normal_form([f], I; nr_thrds, info_level)
49+
return nf[1]
50+
end
51+
52+
@doc Markdown.doc"""
53+
normal_form(
54+
F::Vector{T},
55+
I::Ideal{T};
56+
nr_thrds::Int=1,
57+
info_level::Int=0
58+
) where T <: MPolyRingElem
59+
60+
Compute the normal forms of the elements of `F` w.r.t. a degree reverse
61+
lexicographical Gröbner basis of `I`.
62+
63+
**Note:** If `I` has not already cached a degree reverse lexicographical
64+
Gröbner basis, then this one is first computed.
65+
66+
# Arguments
67+
- `F::Vector{T} where T <: MPolyRingElem`: elements to be reduced.
68+
- `I::Ideal{T} where T <: MPolyRingElem`: ideal data to reduce with.
69+
- `nr_thrds::Int=1`: number of threads for parallel linear algebra.
70+
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
71+
72+
# Examples
73+
```jldoctest
74+
julia> using AlgebraicSolving
75+
76+
julia> R, (x,y) = polynomial_ring(GF(101),["x","y"])
77+
(Multivariate polynomial ring in 2 variables over GF(101), fpMPolyRingElem[x, y])
78+
79+
julia> I = Ideal([y*x^3+12-y, x+y])
80+
fpMPolyRingElem[x^3*y + 100*y + 12, x + y]
81+
82+
julia> F = [2*x^2+7*x*y, x+y]
83+
2-element Vector{fpMPolyRingElem}:
84+
2*x^2 + 7*x*y
85+
x + y
86+
87+
julia> normal_form(F,I)
88+
2-element Vector{fpMPolyRingElem}:
89+
96*y^2
90+
0
91+
```
92+
"""
93+
function normal_form(
94+
F::Vector{T},
95+
I::Ideal{T};
96+
nr_thrds::Int=1,
97+
info_level::Int=0
98+
) where T <: MPolyRingElem
99+
return _core_normal_form(F, I; nr_thrds, info_level)
100+
end
101+
102+
function _core_normal_form(
103+
F::Vector{T},
104+
I::Ideal{T};
105+
nr_thrds::Int=1,
106+
info_level::Int=0
107+
) where T <: MPolyRingElem
108+
109+
110+
if (length(F) == 0 || length(I.gens) == 0)
111+
error("Input data not valid.")
112+
end
113+
114+
R = first(F).parent
115+
nr_vars = nvars(R)
116+
field_char = Int(characteristic(R))
117+
118+
if !(is_probable_prime(field_char))
119+
error("At the moment we only supports finite fields.")
120+
end
121+
122+
#= first get a degree reverse lexicographical Gröbner basis for I =#
123+
G = groebner_basis(I, eliminate = 0, la_option = 44, info_level = info_level)
124+
125+
tbr_nr_gens = length(F)
126+
bs_nr_gens = length(G)
127+
is_gb = 1
128+
129+
# convert ideal to flattened arrays of ints
130+
tbr_lens, tbr_cfs, tbr_exps = _convert_to_msolve(F)
131+
bs_lens, bs_cfs, bs_exps = _convert_to_msolve(G)
132+
133+
nf_ld = Ref(Cint(0))
134+
nf_len = Ref(Ptr{Cint}(0))
135+
nf_exp = Ref(Ptr{Cint}(0))
136+
nf_cf = Ref(Ptr{Cvoid}(0))
137+
138+
nr_terms = ccall((:export_nf, libneogb), Int,
139+
(Ptr{Nothing}, Ptr{Cint}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
140+
Cint, Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Cint, Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid},
141+
Cint, Cint, Cint, Cint, Cint, Cint, Cint),
142+
cglobal(:jl_malloc), nf_ld, nf_len, nf_exp, nf_cf, tbr_nr_gens, tbr_lens, tbr_exps,
143+
tbr_cfs, bs_nr_gens, bs_lens, bs_exps, bs_cfs, field_char, 0, 0, nr_vars, is_gb,
144+
nr_thrds, info_level)
145+
146+
# convert to julia array, also give memory management to julia
147+
jl_ld = nf_ld[]
148+
jl_len = Base.unsafe_wrap(Array, nf_len[], jl_ld)
149+
jl_exp = Base.unsafe_wrap(Array, nf_exp[], nr_terms*nr_vars)
150+
ptr = reinterpret(Ptr{Int32}, nf_cf[])
151+
jl_cf = Base.unsafe_wrap(Array, ptr, nr_terms)
152+
153+
basis = _convert_finite_field_array_to_abstract_algebra(
154+
jl_ld, jl_len, jl_cf, jl_exp, R, 0)
155+
156+
ccall((:free_f4_julia_result_data, libneogb), Nothing ,
157+
(Ptr{Nothing}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}},
158+
Ptr{Ptr{Cvoid}}, Int, Int),
159+
cglobal(:jl_free), nf_len, nf_exp, nf_cf, jl_ld, field_char)
160+
161+
return basis
162+
end
163+

src/exports.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export polynomial_ring, MPolyRing, GFElem, MPolyRingElem, finite_field, GF, fpMPolyRingElem,
22
characteristic, degree, ZZ, QQ, vars, nvars, ngens, ZZRingElem, QQFieldElem, QQMPolyRingElem,
3-
base_ring, coefficient_ring, evaluate, prime_field, sig_groebner_basis, cyclic
3+
base_ring, coefficient_ring, evaluate, prime_field, sig_groebner_basis, cyclic, leading_coefficient

src/imports.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import Nemo:
3434
is_unit,
3535
isqrtrem,
3636
jacobi_symbol,
37+
leading_coefficient,
3738
matrix_space,
3839
moebius_mu,
3940
MPolyRing,

0 commit comments

Comments
 (0)