Skip to content

Commit f1c2b03

Browse files
committed
Allow parallel Gröbner basis computations
1 parent 7fff6a4 commit f1c2b03

4 files changed

Lines changed: 67 additions & 1 deletion

File tree

Project.toml

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

66
[deps]
7+
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
78
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
89
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
910
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
@@ -20,6 +21,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2021
test = ["Test"]
2122

2223
[compat]
24+
Distributed = "1.6"
2325
LinearAlgebra = "1.6"
2426
Logging = "1.6"
2527
Markdown = "1.6"

src/algorithms/groebner-bases.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ At the moment the underlying algorithm is based on variants of Faugère's F4 Alg
2424
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`.
2525
- `normalize::Bool=false`: normalize generators of Gröbner basis for `I`, only applicable when working over the rationals.
2626
- `truncate_lifting::Int=0`: truncates the lifting process to given number of elements, only applicable when working over the rationals.
27+
- `worker_pool::Union{Nothing,AbstractWorkerPool}=nothing`: run the Gröbner basis computation on a worker from the given pool, if not `nothing`.
2728
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
2829
2930
# Examples
@@ -52,6 +53,7 @@ function eliminate(
5253
complete_reduction::Bool=true,
5354
normalize::Bool=false,
5455
truncate_lifting::Int=0,
56+
worker_pool::Union{Nothing,AbstractWorkerPool}=nothing,
5557
info_level::Int=0
5658
)
5759
if eliminate <= 0
@@ -63,6 +65,7 @@ function eliminate(
6365
complete_reduction=complete_reduction,
6466
normalize = normalize,
6567
truncate_lifting = truncate_lifting,
68+
worker_pool = worker_pool,
6669
info_level=info_level)
6770
end
6871
end
@@ -86,6 +89,7 @@ At the moment the underlying algorithm is based on variants of Faugère's F4 Alg
8689
- `complete_reduction::Bool=true`: compute a reduced Gröbner basis for `I`.
8790
- `normalize::Bool=false`: normalize generators of Gröbner basis for `I`, only applicable when working over the rationals.
8891
- `truncate_lifting::Int=0`: truncates the lifting process to given number of elements, only applicable when working over the rationals.
92+
- `worker_pool::Union{Nothing,AbstractWorkerPool}=nothing`: if not `nothing`, run the core Gröbner-basis array computation on a worker from this pool.
8993
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
9094
9195
# Examples
@@ -121,6 +125,7 @@ function groebner_basis(
121125
complete_reduction::Bool=true,
122126
normalize::Bool=false,
123127
truncate_lifting::Int=0,
128+
worker_pool::Union{Nothing,AbstractWorkerPool}=nothing,
124129
info_level::Int=0
125130
)
126131
return get!(I.gb, eliminate) do
@@ -130,6 +135,7 @@ function groebner_basis(
130135
complete_reduction = complete_reduction,
131136
normalize = normalize,
132137
truncate_lifting = truncate_lifting,
138+
worker_pool = worker_pool,
133139
info_level = info_level)
134140
end
135141
end
@@ -235,6 +241,7 @@ function _core_groebner_basis(
235241
complete_reduction::Bool=true,
236242
normalize::Bool=false,
237243
truncate_lifting::Int=0,
244+
worker_pool::Union{Nothing,AbstractWorkerPool}=nothing,
238245
info_level::Int=0
239246
)
240247
F = I.gens
@@ -272,13 +279,19 @@ function _core_groebner_basis(
272279
return I.gb[eliminate]
273280
end
274281

275-
jl_len, jl_cf, jl_exp = _core_groebner_basis_array(
282+
run_core_array = () -> _core_groebner_basis_array(
276283
lens, cfs, exps, field_char;
277284
initial_hts=initial_hts, nr_thrds=nr_thrds,
278285
max_nr_pairs=max_nr_pairs, la_option=la_option, eliminate=eliminate,
279286
complete_reduction=complete_reduction, truncate_lifting=truncate_lifting,
280287
info_level=info_level)
281288

289+
jl_len, jl_cf, jl_exp = if isnothing(worker_pool)
290+
run_core_array()
291+
else
292+
remotecall_fetch(run_core_array, worker_pool)
293+
end
294+
282295
jl_ld = Int32(length(jl_len))
283296
nr_terms = length(jl_exp) ÷ nr_vars
284297

src/imports.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ using StaticArrays
77
import Random: MersenneTwister
88
import Logging: ConsoleLogger, with_logger, Warn, Info
99
import Printf: @sprintf, @printf
10+
import Distributed: AbstractWorkerPool, remotecall_fetch
1011

1112
import Nemo:
1213
bell,

test/algorithms/groebner-bases.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Distributed
2+
13
@testset "Algorithms -> Gröbner bases" begin
24
R, (x,y,z) = polynomial_ring(GF(101),["x","y","z"], internal_ordering=:degrevlex)
35
I = Ideal([x+2*y+2*z-1, x^2+2*y^2+2*z^2-x, 2*x*y+2*y*z-y])
@@ -164,6 +166,54 @@ end
164166
@test (gb_lens, gb_cfs, gb_exps) == AlgebraicSolving._core_groebner_basis_array(lens, cfs, exps, field_char)
165167
end
166168

169+
@testset "Algorithms -> Gröbner bases with workers" begin
170+
_, (x, y, z) = polynomial_ring(GF(101), ["x", "y", "z"], internal_ordering=:degrevlex)
171+
F1 = [x + 2 * y + 2 * z - 1, x^2 + 2 * y^2 + 2 * z^2 - x, 2 * x * y + 2 * y * z - y]
172+
H1 = MPolyRingElem[
173+
x + 2 * y + 2 * z + 100
174+
y * z + 82 * z^2 + 10 * y + 40 * z
175+
y^2 + 60 * z^2 + 20 * y + 81 * z
176+
z^3 + 28 * z^2 + 64 * y + 13 * z
177+
]
178+
179+
_, (x1, x2) = polynomial_ring(QQ, ["x1", "x2"])
180+
F2 = [3 * x1^2 + ZZ(2)^100, 2 * x1 * x2 + 5 * x1 + ZZ(2)^100]
181+
H2 = MPolyRingElem[
182+
3 * x1 - 2 * x2 - 5
183+
4 * x2^2 + 20 * x2 + 3802951800684688204490109616153
184+
]
185+
186+
_, (x, y, z) = polynomial_ring(GF(17), ["x", "y", "z"], internal_ordering=:degrevlex)
187+
F3 = [x^2 + 1 - 3, x * y - z, x * z^2 - 3 * y^2]
188+
H3 = MPolyRingElem[
189+
z^2
190+
y * z
191+
x * z + 15 * y
192+
y^2
193+
x * y + 16 * z
194+
x^2 + 15
195+
]
196+
197+
nb_tests = 42
198+
F = [F1, F2, F3]
199+
G = Vector{Vector{MPolyRingElem}}(undef, nb_tests)
200+
H = [H1, H2, H3]
201+
202+
nb_workers = 2
203+
worker_ids = addprocs(nb_workers; exeflags="--project=$(Base.active_project())")
204+
@everywhere worker_ids using AlgebraicSolving
205+
worker_pool = WorkerPool(worker_ids)
206+
207+
Threads.@threads for i in 1:nb_tests
208+
G[i] = groebner_basis(Ideal(F[i%3+1]), worker_pool=worker_pool)
209+
end
210+
for i in 1:nb_tests
211+
@test G[i] == H[i%3+1]
212+
end
213+
214+
rmprocs(worker_ids)
215+
end
216+
167217
@testset "Algorithms -> Sig Gröbner bases" begin
168218
R, (x,y,z) = polynomial_ring(QQ,["x","y","z"], internal_ordering=:degrevlex)
169219
F = [x^2+1-3, x*y-z, x*z^2-3*y^2]

0 commit comments

Comments
 (0)