Skip to content

Commit c8a7f86

Browse files
committed
Allow calls to _core_msolve with inputs in msolve format
1 parent ac20665 commit c8a7f86

1 file changed

Lines changed: 144 additions & 72 deletions

File tree

src/algorithms/solvers.jl

Lines changed: 144 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,165 @@ Construct the rational parametrization of the solution set computed via msolve.
1212
function _get_rational_parametrization(
1313
nr::Int32,
1414
lens::Vector{Int32},
15-
cfs::Ptr{BigInt},
16-
cfs_lf::Ptr{BigInt},
15+
cfs::Vector{BigInt},
16+
cfs_lf::Vector{BigInt},
1717
nr_vars::Int32
1818
)
19-
if cfs_lf != Ptr{BigInt}(0)
20-
lf = [ZZRingElem(unsafe_load(cfs_lf, i)) for i in 1:nr_vars]
19+
if !isempty(cfs_lf)
20+
lf = [ZZRingElem(cfs_lf[i]) for i in 1:nr_vars]
2121
else
2222
lf = ZZRingElem[]
2323
end
2424
C, x = polynomial_ring(QQ,"x")
2525
ctr = 0
2626

27-
elim = C([unsafe_load(cfs, i) for i in 1:lens[1]])
27+
elim = C([cfs[i] for i in 1:lens[1]])
2828
ctr += lens[1]
2929

30-
denom = C([unsafe_load(cfs, i+ctr) for i in 1:lens[2]])
30+
denom = C([cfs[i+ctr] for i in 1:lens[2]])
3131
ctr += lens[2]
3232

3333
size = nr-2
3434
p = Vector{QQPolyRingElem}(undef, size)
3535
k = 1
3636
for i in 3:nr
37-
p[k] = C([unsafe_load(cfs, j+ctr) for j in 1:lens[i]-1])
37+
p[k] = C([cfs[j+ctr] for j in 1:lens[i]-1])
3838
# multiply parametrization polynomial directly with
3939
# corresponding coefficients
40-
p[k] *= (-1) // ZZRingElem(unsafe_load(cfs, lens[i]+ctr))
40+
p[k] *= (-1) // ZZRingElem(cfs[lens[i]+ctr])
4141
ctr += lens[i]
4242
k += 1
4343
end
4444

4545
return lf, elim, denom, p
4646
end
4747

48+
@doc Markdown.doc"""
49+
_core_msolve_array(lens::Vector{Int32}, cfs::Union{Vector{Int32},Vector{BigInt}}, exps::Vector{Int32}, variable_names::Vector{String}, field_char::Int; <keyword arguments>)
50+
51+
Compute a rational parametrization and the real solutions of the ideal via msolve.
52+
53+
**Note**: Both the input and output of this function are given as flattened arrays of integers and strings instead of polynomials.
54+
55+
# Arguments
56+
- `lens::Vector{Int32}`: vector of number of terms per generator.
57+
- `cfs::Union{Vector{Int32},Vector{BigInt}}`: vector of coefficients of all generators, concatenated. When working over the rationals, the coefficients are given as pairs of numerators and denominators, i.e. `cfs[2*i-1]` is the numerator and `cfs[2*i]` the denominator of the `i`-th coefficient.
58+
- `exps::Vector{Int32}`: vector of exponent vectors of all generators, concatenated.
59+
- `variable_names::Vector{String}`: vector of variable names.
60+
- `field_char::Int`: characteristic of the ground field, `0` for the rationals.
61+
- `initial_hts::Int=17`: initial hash table size `log_2`.
62+
- `nr_thrds::Int=1`: number of threads for parallel linear algebra.
63+
- `max_nr_pairs::Int=0`: maximal number of pairs per matrix, only bounded by minimal degree if `0`.
64+
- `la_option::Int=2`: linear algebra option: exact sparse-dense (`1`), exact sparse (`2`, default), probabilistic sparse-dense (`42`), probabilistic sparse(`44`).
65+
- `get_param::Int=1`: parametrization option: no (`0`), yes (`1`, default), only rational parametrization, no solutions are computed (`2`).
66+
- `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
67+
- `precision::Int=32`: bit precision for the computed solutions.
68+
```
69+
70+
**Note**: This is an internal function.
71+
"""
72+
function _core_msolve_array(
73+
lens::Vector{Int32},
74+
cfs::Union{Vector{Int32},Vector{BigInt}},
75+
exps::Vector{Int32},
76+
variable_names::Vector{String},
77+
field_char::Int;
78+
initial_hts::Int=17,
79+
nr_thrds::Int=1,
80+
max_nr_pairs::Int=0,
81+
la_option::Int=2,
82+
get_param::Int=1,
83+
info_level::Int=0,
84+
precision::Int=32
85+
)::Tuple{Vector{Int32},Vector{String},Vector{BigInt},Vector{BigInt},Vector{BigInt},Vector{Int32}}
86+
if field_char != 0
87+
error("At the moment we only support the rationals as ground field.")
88+
end
89+
90+
nr_gens = length(lens)
91+
nr_vars = length(exps) ÷ sum(lens)
92+
93+
#= add new variables and linear forms, =#
94+
genericity_handling = 2
95+
96+
reset_ht = 0
97+
print_gb = 0
98+
99+
mon_order = 0
100+
elim_block_size = 0
101+
use_signatures = 0
102+
103+
res_ld = Ref(Cint(0))
104+
res_nr_vars = Ref(Cint(0))
105+
res_dim = Ref(Cint(0))
106+
res_dquot = Ref(Cint(0))
107+
nb_sols = Ref(Cint(0))
108+
res_len = Ref(Ptr{Cint}(0))
109+
res_vnames = Ref(Ptr{Ptr{Cchar}}(0))
110+
res_cf_lf = Ref(Ptr{Cvoid}(0))
111+
res_cf = Ref(Ptr{Cvoid}(0))
112+
sols_num = Ref(Ptr{Cvoid}(0))
113+
sols_den = Ref(Ptr{Cint}(0))
114+
115+
ccall((:msolve_julia, libmsolve), Cvoid,
116+
(Ptr{Nothing}, Ptr{Cint}, Ptr{Cint}, Ptr{Cint}, Ptr{Cint},
117+
Ptr{Ptr{Cint}}, Ptr{Ptr{Ptr{Cchar}}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cint}, Ptr{Cvoid}, Ptr{Ptr{Cint}},
118+
Ptr{Cint}, Ptr{Cint}, Ptr{Cvoid}, Ptr{Ptr{Cchar}}, Ptr{Cchar}, Cint, Cint,
119+
Cint, Cint, Cint, Cint, Cint, Cint, Cint, Cint,
120+
Cint, Cint, Cint, Cint, Cint, Cint),
121+
cglobal(:jl_malloc), res_ld, res_nr_vars, res_dim, res_dquot,
122+
res_len, res_vnames, res_cf_lf, res_cf, nb_sols, sols_num, sols_den,
123+
lens, exps, cfs, variable_names, "/dev/null", field_char, mon_order,
124+
elim_block_size, nr_vars, nr_gens, initial_hts, nr_thrds, max_nr_pairs, reset_ht, la_option,
125+
use_signatures, print_gb, get_param, genericity_handling, precision, info_level)
126+
127+
# convert to julia array, also give memory management to julia
128+
jl_ld = res_ld[]
129+
jl_rp_nr_vars = res_nr_vars[]
130+
jl_dim = res_dim[]
131+
jl_dquot = res_dquot[]
132+
133+
if jl_dim > 0
134+
error("Dimension of ideal is greater than zero, no solutions provided.")
135+
end
136+
137+
if jl_dquot == 0
138+
return Int32[], String[], BigInt[], BigInt[], BigInt[], Int32[]
139+
end
140+
141+
# get rational parametrization
142+
jl_len = Int32.(Base.unsafe_wrap(Array, res_len[], jl_ld))
143+
144+
jl_vnames_ptrs = Base.unsafe_wrap(Array, res_vnames[], jl_rp_nr_vars)
145+
jl_vnames = [unsafe_string(jl_vnames_ptrs[i]) for i in 1:jl_rp_nr_vars]
146+
147+
jl_cf_lf_ptr = reinterpret(Ptr{BigInt}, res_cf_lf[])
148+
if jl_cf_lf_ptr != Ptr{BigInt}(0)
149+
jl_cf_lf = BigInt.([deepcopy(unsafe_load(jl_cf_lf_ptr, i)) for i in 1:jl_rp_nr_vars])
150+
else
151+
jl_cf_lf = BigInt[]
152+
end
153+
jl_cf_ptr = reinterpret(Ptr{BigInt}, res_cf[])
154+
jl_cf = BigInt.([deepcopy(unsafe_load(jl_cf_ptr, i)) for i in 1:sum(jl_len)])
155+
156+
jl_nb_sols = nb_sols[]
157+
158+
# get solutions
159+
len = 2 * jl_nb_sols * nr_vars
160+
jl_sols_num_ptr = reinterpret(Ptr{BigInt}, sols_num[])
161+
jl_sols_num = BigInt.([deepcopy(unsafe_load(jl_sols_num_ptr, i)) for i in 1:len])
162+
jl_sols_den_ptr = reinterpret(Ptr{Int32}, sols_den[])
163+
jl_sols_den = Int32.(Base.unsafe_wrap(Array, jl_sols_den_ptr, len))
164+
165+
ccall((:free_msolve_julia_result_data, libmsolve), Nothing,
166+
(Ptr{Nothing}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
167+
Ptr{Ptr{Cvoid}}, Ptr{Ptr{Cint}}, Cint, Cint, Cint),
168+
cglobal(:jl_free), res_len, res_cf, sols_num, sols_den,
169+
jl_ld, jl_nb_sols, field_char)
170+
171+
return jl_len, jl_vnames, jl_cf_lf, jl_cf, jl_sols_num, jl_sols_den
172+
end
173+
48174
@doc Markdown.doc"""
49175
_core_msolve(I::Ideal{T} where T <: MPolyRingElem, <keyword arguments>)
50176
@@ -75,64 +201,27 @@ function _core_msolve(
75201

76202
variable_names = map(string, R.S)
77203

78-
#= add new variables and linear forms, =#
79-
genericity_handling = 2
80-
81-
reset_ht = 0
82-
print_gb = 0
83-
84-
mon_order = 0
85-
elim_block_size = 0
86-
use_signatures = 0
87-
88204
if field_char != 0
89205
error("At the moment we only support the rationals as ground field.")
90206
end
91207
# convert Singular ideal to flattened arrays of ints
92208
lens, cfs, exps, nr_gens = _convert_to_msolve(F)
93209

94-
res_ld = Ref(Cint(0))
95-
res_nr_vars = Ref(Cint(0))
96-
res_dim = Ref(Cint(0))
97-
res_dquot = Ref(Cint(0))
98-
nb_sols = Ref(Cint(0))
99-
res_len = Ref(Ptr{Cint}(0))
100-
res_vnames = Ref(Ptr{Ptr{Cchar}}(0))
101-
res_cf_lf = Ref(Ptr{Cvoid}(0))
102-
res_cf = Ref(Ptr{Cvoid}(0))
103-
sols_num = Ref(Ptr{Cvoid}(0))
104-
sols_den = Ref(Ptr{Cint}(0))
210+
jl_len, jl_vnames, jl_cf_lf, jl_cf, jl_sols_num, jl_sols_den =
211+
_core_msolve_array(lens, cfs, exps, variable_names, field_char;
212+
initial_hts, nr_thrds, max_nr_pairs, la_option, get_param, info_level, precision)
105213

106-
ccall((:msolve_julia, libmsolve), Cvoid,
107-
(Ptr{Nothing}, Ptr{Cint}, Ptr{Cint}, Ptr{Cint}, Ptr{Cint}, Ptr{Ptr{Cint}},
108-
Ptr{Ptr{Ptr{Cchar}}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cint}, Ptr{Cvoid}, Ptr{Ptr{Cint}}, Ptr{Cint},
109-
Ptr{Cint}, Ptr{Cvoid}, Ptr{Ptr{Cchar}}, Ptr{Cchar}, Cint, Cint,
110-
Cint, Cint, Cint, Cint, Cint, Cint, Cint, Cint, Cint, Cint, Cint,
111-
Cint, Cint, Cint),
112-
cglobal(:jl_malloc), res_ld, res_nr_vars, res_dim, res_dquot, res_len, res_vnames,
113-
res_cf_lf, res_cf,
114-
nb_sols, sols_num, sols_den, lens, exps, cfs, variable_names,
115-
"/dev/null", field_char, mon_order, elim_block_size, nr_vars,
116-
nr_gens, initial_hts, nr_thrds, max_nr_pairs, reset_ht, la_option,
117-
use_signatures, print_gb, get_param, genericity_handling, precision,
118-
info_level)
119214
# convert to julia array, also give memory management to julia
120-
jl_ld = res_ld[]
121-
jl_rp_nr_vars = res_nr_vars[]
122-
jl_dim = res_dim[]
123-
jl_dquot = res_dquot[]
124-
jl_nb_sols = nb_sols[]
215+
jl_ld = Int32(length(jl_len))
216+
jl_rp_nr_vars = Int32(length(jl_vnames))
217+
jl_nb_sols = length(jl_sols_num) ÷ (2 * nr_vars)
125218

126-
if jl_dim > 0
127-
error("Dimension of ideal is greater than zero, no solutions provided.")
128-
end
129219
I.dim = 0
130220

131221
# get rational parametrization
132-
jl_len = Base.unsafe_wrap(Array, res_len[], jl_ld)
133222
nterms = 0
134223

135-
if jl_dquot == 0
224+
if jl_ld == 0
136225
I.dim = -1
137226
C,x = polynomial_ring(QQ,"x")
138227
I.rat_param = RationalParametrization(Symbol[], ZZRingElem[], C(-1), C(-1), QQPolyRingElem[])
@@ -141,11 +230,8 @@ function _core_msolve(
141230
return I.rat_param, I.real_sols
142231
end
143232
[nterms += jl_len[i] for i=1:jl_ld]
144-
jl_cf = reinterpret(Ptr{BigInt}, res_cf[])
145-
jl_cf_lf = reinterpret(Ptr{BigInt}, res_cf_lf[])
146233

147-
jl_vnames = Base.unsafe_wrap(Array, res_vnames[], jl_rp_nr_vars)
148-
vsymbols = [Symbol(unsafe_string(jl_vnames[i])) for i in 1:jl_rp_nr_vars]
234+
vsymbols = [Symbol(jl_vnames[i]) for i in 1:jl_rp_nr_vars]
149235
#= get possible variable permutation, ignoring additional variables=#
150236
perm = indexin(R.S, vsymbols)
151237

@@ -165,14 +251,6 @@ function _core_msolve(
165251
return rat_param, Vector{QQFieldElem}[]
166252
end
167253

168-
# get solutions
169-
jl_sols_num = reinterpret(Ptr{BigInt}, sols_num[])
170-
jl_sols_den = reinterpret(Ptr{Int32}, sols_den[])
171-
# elseif is_prime(field_char)
172-
# jl_cf = reinterpret(Ptr{Int32}, res_cf[])
173-
# jl_sols_num = reinterpret(Ptr{Int32}, sols_num[])
174-
# end
175-
176254
#= solutions are returned as intervals, i.e. a minimum and a maximum entry for
177255
= the numerator and denominator; we also sum up and divide by 2 =#
178256

@@ -188,8 +266,8 @@ function _core_msolve(
188266
tmp = Vector{QQFieldElem}(undef, nr_vars)
189267
while j <= nr_vars
190268
inter_tmp_coeff = Vector{QQFieldElem}(undef, 2)
191-
inter_tmp_coeff[1] = QQFieldElem(unsafe_load(jl_sols_num, i)) >> Int64(unsafe_load(jl_sols_den, i))
192-
inter_tmp_coeff[2] = QQFieldElem(unsafe_load(jl_sols_num, i+1)) >> Int64(unsafe_load(jl_sols_den, i+1))
269+
inter_tmp_coeff[1] = QQFieldElem(jl_sols_num[i]) >> Int64(jl_sols_den[i])
270+
inter_tmp_coeff[2] = QQFieldElem(jl_sols_num[i+1]) >> Int64(jl_sols_den[i+1])
193271
inter_tmp[perm[j]] = inter_tmp_coeff
194272
tmp[perm[j]] = sum(inter_tmp_coeff) >> 1
195273
i += 2
@@ -202,12 +280,6 @@ function _core_msolve(
202280
I.inter_sols = inter_solutions
203281
I.real_sols = solutions
204282

205-
ccall((:free_msolve_julia_result_data, libmsolve), Nothing ,
206-
(Ptr{Nothing}, Ptr{Ptr{Cint}}, Ptr{Ptr{Cvoid}},
207-
Ptr{Ptr{Cvoid}}, Ptr{Ptr{Cint}}, Cint, Cint, Cint),
208-
cglobal(:jl_free), res_len, res_cf, sols_num, sols_den,
209-
jl_ld, jl_nb_sols, field_char)
210-
211283
return rat_param, solutions
212284
end
213285

0 commit comments

Comments
 (0)