@@ -248,14 +248,107 @@ function rational_parametrization(
248248 return I. rat_param
249249end
250250
251+
252+ @doc Markdown. doc"""
253+ rational_solutions(I::Ideal{T} where T <: MPolyElem, <keyword arguments>)
254+
255+ Given an ideal `I` with a finite solution set over the complex numbers, return
256+ the rational roots of the ideal.
257+
258+ # Arguments
259+ - `I::Ideal{T} where T <: MPolyElem`: input generators.
260+ - `initial_hts::Int=17`: initial hash table size `log_2`.
261+ - `nr_thrds::Int=1`: number of threads for parallel linear algebra.
262+ - `max_nr_pairs::Int=0`: maximal number of pairs per matrix, only bounded by minimal degree if `0`.
263+ - `la_option::Int=2`: linear algebra option: exact sparse-dense (`1`), exact sparse (`2`, default), probabilistic sparse-dense (`42`), probabilistic sparse(`44`).
264+ - `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
265+ - `precision::Int=32`: bit precision for the computed solutions.
266+
267+ # Examples
268+ ```jldoctest
269+ julia> using AlgebraicSolving
270+
271+ julia> R,(x1,x2,x3) = PolynomialRing(QQ, ["x1","x2","x3"])
272+ (Multivariate Polynomial Ring in x1, x2, x3 over Rational Field, Nemo.fmpq_mpoly[x1, x2, x3])
273+
274+ julia> I = Ideal([x1+2*x2+2*x3-1, x1^2+2*x2^2+2*x3^2-x1, 2*x1*x2+2*x2*x3-x2])
275+ Nemo.fmpq_mpoly[x1 + 2*x2 + 2*x3 - 1, x1^2 - x1 + 2*x2^2 + 2*x3^2, 2*x1*x2 + 2*x2*x3 - x2]
276+
277+ julia> rat_sols = rational_solutions(I)
278+ 2-element Vector{Vector{fmpq}}:
279+ [1, 0, 0]
280+ [1//3, 0, 1//3]
281+
282+ julia> map(r->map(p->evaluate(p, r), I.gens), rat_sols)
283+ 4-element Vector{Vector{fmpq}}:
284+ [0, 0, 0]
285+ [0, 0, 0]
286+
287+ """
288+ function rational_solutions (
289+ I:: Ideal{T} where T <: MPolyElem ; # input generators
290+ initial_hts:: Int = 17 , # hash table size, default 2^17
291+ nr_thrds:: Int = 1 , # number of threads
292+ max_nr_pairs:: Int = 0 , # number of pairs maximally chosen
293+ # in symbolic preprocessing
294+ la_option:: Int = 2 , # linear algebra option
295+ info_level:: Int = 0 , # info level for print outs
296+ precision:: Int = 32 # precision of the solution set
297+ )
298+ isdefined (I, :rat_param ) ||
299+ _core_msolve (I,
300+ initial_hts = initial_hts,
301+ nr_thrds = nr_thrds,
302+ max_nr_pairs = max_nr_pairs,
303+ la_option = la_option,
304+ info_level = info_level,
305+ precision = precision)
306+ param_t = I. rat_param
307+
308+ nvars = length (param_t. vars)
309+ lpol = filter (l-> degree (l) == 1 , keys (factor (param_t. elim). fac))
310+ nb = length (lpol)
311+
312+ rat_elim = [- coeff (l, 0 )// coeff (l, 1 ) for l in lpol]
313+ rat_den = map (l-> evaluate (param_t. denom, l), rat_elim)
314+ rat_num = map (r-> map (l-> evaluate (l, r), param_t. param), rat_elim)
315+
316+ rat_sols = Vector {Vector{fmpq}} (undef, nb)
317+
318+ if length (param_t. vars) == parent (I). nvars
319+
320+ for i in 1 : nb
321+ rat_sols[i] = Vector {fmpq} (undef, nvars)
322+ for j in 1 : (nvars- 1 )
323+ rat_sols[i][j] = rat_num[i][j] // rat_den[i]
324+ end
325+ rat_sols[i][nvars] = rat_elim[i]
326+ end
327+
328+ else
329+
330+ for i in 1 : nb
331+ rat_sols[i] = Vector {fmpq} (undef, nvars - 1 )
332+ for j in 1 : (nvars- 1 )
333+ rat_sols[i][j] = rat_num[i][j] // rat_den[i]
334+ end
335+ end
336+
337+ end
338+
339+ return rat_sols
340+
341+ end
342+
343+
251344@doc Markdown. doc"""
252345 real_solutions(I::Ideal{T} where T <: MPolyElem, <keyword arguments>)
253346
254347Given an ideal `I` with a finite solution set over the complex numbers, return
255348the real roots of the ideal with a given precision (default 32 bits).
256349
257350**Note**: At the moment only QQ is supported as ground field. If the dimension of the ideal
258- is greater then zero an empty array is returned.
351+ is greater than zero an empty array is returned.
259352
260353# Arguments
261354- `I::Ideal{T} where T <: MPolyElem`: input generators.
0 commit comments