Skip to content

Commit 142d1f2

Browse files
committed
adds julia side of computing gbs over QQ via msolve
1 parent 67cf4d4 commit 142d1f2

File tree

3 files changed

+118
-19
lines changed

3 files changed

+118
-19
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ authors = ["ederc <[email protected]>", "Mohab Safey El Din <Mohab.Safe
44
version = "0.5.1"
55

66
[deps]
7+
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
78
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
89
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
910
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
@@ -15,6 +16,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1516
msolve_jll = "6d01cc9a-e8f6-580e-8c54-544227e08205"
1617

1718
[compat]
19+
Libdl = "1.10"
1820
LinearAlgebra = "1.6"
1921
Logging = "1.6"
2022
Markdown = "1.6"

src/algorithms/groebner-bases.jl

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import msolve_jll: libneogb
22

33
export groebner_basis, eliminate
44

5+
using Libdl
6+
57
@doc Markdown.doc"""
68
eliminate(I::Ideal{T} where T <: MPolyRingElem, eliminate::Int, <keyword arguments>)
79
@@ -11,7 +13,7 @@ the first `eliminate` variables.
1113
1214
At the moment the underlying algorithm is based on variants of Faugère's F4 Algorithm.
1315
14-
**Note**: At the moment only ground fields of characteristic `p`, `p` prime, `p < 2^{31}` are supported.
16+
**Note**: At the moment only ground fields of characteristic `p`, `p` prime, `p < 2^{31}` and the rationals are supported.
1517
1618
# Arguments
1719
- `I::Ideal{T} where T <: MPolyRingElem`: input generators.
@@ -21,7 +23,8 @@ At the moment the underlying algorithm is based on variants of Faugère's F4 Alg
2123
- `nr_thrds::Int=1`: number of threads for parallel linear algebra.
2224
- `max_nr_pairs::Int=0`: maximal number of pairs per matrix, only bounded by minimal degree if `0`.
2325
- `la_option::Int=2`: linear algebra option: exact sparse-dense (`1`), exact sparse (`2`, default), probabilistic sparse-dense (`42`), probabilistic sparse(`44`).
24-
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`
26+
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`.
27+
- `normalize::Bool=false`: normalize generators of Gröbner basis for `I`, only applicable when working over the rationals.
2528
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
2629
2730
# Examples
@@ -48,6 +51,7 @@ function eliminate(
4851
max_nr_pairs::Int=0,
4952
la_option::Int=2,
5053
complete_reduction::Bool=true,
54+
normalize::Bool=false,
5155
info_level::Int=0
5256
)
5357
if eliminate <= 0
@@ -67,7 +71,7 @@ end
6771
Compute a Groebner basis of the ideal `I` w.r.t. to the degree reverse lexicographical monomial ordering using Faugère's F4 algorithm.
6872
At the moment the underlying algorithm is based on variants of Faugère's F4 Algorithm.
6973
70-
**Note**: At the moment only ground fields of characteristic `p`, `p` prime, `p < 2^{31}` are supported.
74+
**Note**: At the moment only ground fields of characteristic `p`, `p` prime, `p < 2^{31}` and the rationals are supported.
7175
7276
# Arguments
7377
- `I::Ideal{T} where T <: MPolyRingElem`: input generators.
@@ -77,7 +81,8 @@ At the moment the underlying algorithm is based on variants of Faugère's F4 Alg
7781
- `la_option::Int=2`: linear algebra option: exact sparse-dense (`1`), exact sparse (`2`, default), probabilistic sparse-dense (`42`), probabilistic sparse(`44`).
7882
- `eliminate::Int=0`: size of first block of variables to be eliminated.
7983
- `intersect::Bool=true`: compute the `eliminate`-th elimination ideal.
80-
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`
84+
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`.
85+
- `normalize::Bool=false`: normalize generators of Gröbner basis for `I`, only applicable when working over the rationals.
8186
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
8287
8388
# Examples
@@ -111,6 +116,7 @@ function groebner_basis(
111116
eliminate::Int=0,
112117
intersect::Bool=true,
113118
complete_reduction::Bool=true,
119+
normalize::Bool=false,
114120
info_level::Int=0
115121
)
116122

@@ -132,6 +138,7 @@ function _core_groebner_basis(
132138
eliminate::Int=0,
133139
intersect::Bool=true,
134140
complete_reduction::Bool=true,
141+
normalize::Bool=false,
135142
info_level::Int=0
136143
)
137144

@@ -149,8 +156,11 @@ function _core_groebner_basis(
149156
reduce_gb = Int(complete_reduction)
150157

151158
# convert ideal to flattened arrays of ints
152-
if !(is_probable_prime(field_char))
153-
error("At the moment we only support finite fields.")
159+
160+
if !(field_char == 0)
161+
if !(is_probable_prime(field_char))
162+
error("At the moment we only support finite fields or the rationals.")
163+
end
154164
end
155165

156166
# nr_gens might change if F contains zero polynomials
@@ -160,30 +170,56 @@ function _core_groebner_basis(
160170
gb_len = Ref(Ptr{Cint}(0))
161171
gb_exp = Ref(Ptr{Cint}(0))
162172
gb_cf = Ref(Ptr{Cvoid}(0))
173+
ngb = Libdl.dlopen("/Users/ederc/repos/master-msolve/src/neogb/.libs/libneogb")
174+
175+
msv = Libdl.dlopen("/Users/ederc/repos/master-msolve/src/msolve/.libs/libmsolve")
176+
rr = Libdl.dlsym(msv, :export_groebner_qq)
177+
if field_char == 0
178+
nr_terms = ccall(rr, Int,
179+
(Ptr{Nothing}, Ptr{Cint}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
180+
Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Cint, Cint, Cint, Cint, Cint, Cint,
181+
Cint, Cint, Cint, Cint, Cint, Cint, Cint, Cint),
182+
cglobal(:jl_malloc), gb_ld, gb_len, gb_exp, gb_cf, lens, exps, cfs,
183+
field_char, mon_order, elim_block_size, nr_vars, nr_gens, initial_hts,
184+
nr_thrds, max_nr_pairs, 0, la_option, reduce_gb, 0, 0, info_level)
163185

164-
nr_terms = ccall((:export_f4, libneogb), Int,
165-
(Ptr{Nothing}, Ptr{Cint}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
166-
Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Cint, Cint, Cint, Cint, Cint, Cint,
167-
Cint, Cint, Cint, Cint, Cint, Cint, Cint),
168-
cglobal(:jl_malloc), gb_ld, gb_len, gb_exp, gb_cf, lens, exps, cfs,
169-
field_char, mon_order, elim_block_size, nr_vars, nr_gens, initial_hts,
170-
nr_thrds, max_nr_pairs, 0, la_option, reduce_gb, 0, info_level)
186+
else
187+
nr_terms = ccall((:export_f4, libneogb), Int,
188+
(Ptr{Nothing}, Ptr{Cint}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
189+
Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Cint, Cint, Cint, Cint, Cint, Cint,
190+
Cint, Cint, Cint, Cint, Cint, Cint, Cint),
191+
cglobal(:jl_malloc), gb_ld, gb_len, gb_exp, gb_cf, lens, exps, cfs,
192+
field_char, mon_order, elim_block_size, nr_vars, nr_gens, initial_hts,
193+
nr_thrds, max_nr_pairs, 0, la_option, reduce_gb, 0, info_level)
194+
end
171195

172196
# convert to julia array, also give memory management to julia
173197
jl_ld = gb_ld[]
174198
jl_len = Base.unsafe_wrap(Array, gb_len[], jl_ld)
175199
jl_exp = Base.unsafe_wrap(Array, gb_exp[], nr_terms*nr_vars)
176-
ptr = reinterpret(Ptr{Int32}, gb_cf[])
177-
jl_cf = Base.unsafe_wrap(Array, ptr, nr_terms)
178200

179-
if intersect == true
180-
basis = _convert_finite_field_array_to_abstract_algebra(
201+
# coefficient handling depending on field characteristic
202+
if field_char == 0
203+
ptr = reinterpret(Ptr{BigInt}, gb_cf[])
204+
jl_cf = [QQFieldElem(unsafe_load(ptr, i)) for i in 1:nr_terms]
205+
else
206+
ptr = reinterpret(Ptr{Int32}, gb_cf[])
207+
jl_cf = Base.unsafe_wrap(Array, ptr, nr_terms)
208+
end
209+
210+
# shall eliminated variables be removed?
211+
if !intersect
212+
eliminate = 0
213+
end
214+
215+
# convert to basis
216+
if field_char == 0
217+
basis = _convert_rational_array_to_abstract_algebra(
181218
jl_ld, jl_len, jl_cf, jl_exp, R, eliminate)
182219
else
183220
basis = _convert_finite_field_array_to_abstract_algebra(
184-
jl_ld, jl_len, jl_cf, jl_exp, R, 0)
221+
jl_ld, jl_len, jl_cf, jl_exp, R, eliminate)
185222
end
186-
187223
ccall((:free_f4_julia_result_data, libneogb), Nothing ,
188224
(Ptr{Nothing}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cint}},
189225
Ptr{Ptr{Cvoid}}, Int, Int),

src/interfaces/nemo.jl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,64 @@ function _convert_finite_field_array_to_abstract_algebra(
124124

125125
return basis
126126
end
127+
128+
function _convert_rational_array_to_abstract_algebra(
129+
bld::Int32,
130+
blen::Vector{Int32},
131+
bcf::Vector{QQFieldElem},
132+
bexp::Vector{Int32},
133+
R::MPolyRing,
134+
eliminate::Int=0,
135+
normalize::Bool=false
136+
)
137+
138+
if characteristic(R) != 0
139+
error("We assume QQ as base field here.")
140+
end
141+
142+
nr_gens = bld
143+
nr_vars = nvars(R)
144+
CR = coefficient_ring(R)
145+
146+
basis = (typeof(R(0)))[]
147+
#= basis = Vector{MPolyRingElem}(undef, bld) =#
148+
149+
len = 0
150+
151+
if eliminate > 0
152+
z = zeros(Int, eliminate)
153+
end
154+
for i in 1:nr_gens
155+
println("i ", i)
156+
#= check if element is part of the eliminated basis =#
157+
if eliminate > 0
158+
cmp = convert(Vector{Int}, bexp[(len)*nr_vars+1:(len+1)*nr_vars])
159+
if cmp[1:eliminate] > z
160+
continue
161+
end
162+
end
163+
if bcf[len+1] == 0
164+
push!(basis, R(0))
165+
else
166+
g = MPolyBuildCtx(R)
167+
lc = bcf[len+1]
168+
if normalize && lc == 1
169+
for j in 1:blen[i]
170+
println("j ", j)
171+
push_term!(g, bcf[len+j],
172+
convert(Vector{Int}, bexp[(len+j-1)*nr_vars+1:(len+j)*nr_vars]))
173+
end
174+
else
175+
for j in 1:blen[i]
176+
println("j ", j)
177+
push_term!(g, bcf[len+j]/lc,
178+
convert(Vector{Int}, bexp[(len+j-1)*nr_vars+1:(len+j)*nr_vars]))
179+
end
180+
end
181+
push!(basis, finish(g))
182+
end
183+
len += blen[i]
184+
end
185+
186+
return basis
187+
end

0 commit comments

Comments
 (0)