Skip to content

Commit fb423ac

Browse files
authored
Merge pull request #374 from SciML/bump_groebner
Bump groebner
2 parents d34f4dd + bbae560 commit fb423ac

File tree

14 files changed

+168
-52
lines changed

14 files changed

+168
-52
lines changed

.github/workflows/CI.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ jobs:
1515
- Core
1616
- ModelingToolkitSIExt
1717
version:
18-
- '<1.10.3 || >=1.10.4'
19-
- '1.6'
18+
- '1'
19+
- '1.10'
2020
steps:
2121
- uses: actions/checkout@v4
2222
- uses: julia-actions/setup-julia@v2

Project.toml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,31 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
2929
ModelingToolkitSIExt = ["ModelingToolkit", "SymbolicUtils", "Symbolics"]
3030

3131
[compat]
32-
AbstractAlgebra = "0.40, 0.41, 0.42, 0.43"
32+
AbstractAlgebra = "0.42, 0.43, 0.44"
3333
Aqua = "0.8"
3434
CPUSummary = "0.2"
3535
Combinatorics = "1"
3636
DataStructures = "0.18"
37-
Dates = "1.6, 1.7"
38-
Groebner = "0.7.3"
37+
Dates = "1.10, 1.11"
38+
Groebner = "0.8.1"
3939
IterTools = "1"
40-
LinearAlgebra = "1.6, 1.7"
41-
Logging = "1.6, 1.7"
40+
LinearAlgebra = "1.10, 1.11"
41+
Logging = "1.10, 1.11"
4242
MacroTools = "0.5"
4343
ModelingToolkit = "9.33"
44-
Nemo = "0.43, 0.44, 0.45, 0.46, 0.47"
45-
ParamPunPam = "0.4"
46-
Pkg = "1.6, 1.7"
44+
Nemo = "0.46, 0.47, 0.48"
45+
ParamPunPam = "0.5"
46+
Pkg = "1.10, 1.11"
4747
PrecompileTools = "1.2"
4848
Primes = "0.5"
49-
Random = "1.6, 1.7"
49+
Random = "1.10, 1.11"
5050
SpecialFunctions = "2"
51-
SymbolicUtils = "3.2"
52-
Symbolics = "6.2"
53-
Test = "1.6, 1.7"
51+
SymbolicUtils = "3.7"
52+
Symbolics = "6.16"
53+
Test = "1.10, 1.11"
5454
TestSetExtensions = "2"
5555
TimerOutputs = "0.5"
56-
julia = "1.6 - 1.10.2, 1.10.4, 1.11"
56+
julia = "1.10.4, 1.11.2"
5757

5858
[extras]
5959
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"

benchmarking/IdentifiableFunctions/experiments.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,10 +1478,10 @@ mqs_spec = StructuralIdentifiability.ParamPunPam.specialize_mod_p(mqs, point);
14781478

14791479
Groebner.logging_enabled() = false
14801480

1481-
@time graph, gb = Groebner.groebner_learn(mqs_spec, loglevel = 0, sweep = true);
1482-
@time Groebner.groebner_apply!(graph, mqs_spec, loglevel = 0, sweep = true);
1481+
@time graph, gb = Groebner.groebner_learn(mqs_spec, sweep = true);
1482+
@time Groebner.groebner_apply!(graph, mqs_spec, sweep = true);
14831483

1484-
@benchmark Groebner.groebner_apply!($graph, $mqs_spec, loglevel = 0, sweep = true)
1484+
@benchmark Groebner.groebner_apply!($graph, $mqs_spec, sweep = true)
14851485

14861486
# Results for covid
14871487
#=
@@ -1523,4 +1523,4 @@ BenchmarkTools.Trial: 180 samples with 1 evaluation.
15231523
Memory estimate: 775.77 KiB, allocs estimate: 3662.
15241524
=#
15251525

1526-
@my_profview_allocs Groebner.groebner_apply!(graph, mqs_spec, loglevel = 0, sweep = true);
1526+
@my_profview_allocs Groebner.groebner_apply!(graph, mqs_spec, sweep = true);

benchmarking/IdentifiableFunctions/homogenization.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ ideal_spec = StructuralIdentifiability.specialize_mod_p(mqs, point)
3131
@time gb = groebner(ideal_spec, ordering = Groebner.DegRevLex());
3232

3333
# There is an existent possibility that this would not finish in two and a half lifetimes
34-
# @time gb = groebner(ideal_spec, ordering = Groebner.Lex(), loglevel = -3);
34+
# @time gb = groebner(ideal_spec, ordering = Groebner.Lex());
3535

3636
homogeneous_ideal_spec = StructuralIdentifiability.homogenize(ideal_spec);
3737
# 100 ms

ext/ModelingToolkitSIExt.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,19 @@ function __mtk_to_si(
210210
all_funcs = collect(Set(clean_calls(ModelingToolkit.unknowns(de))))
211211
inputs = filter(s -> !ModelingToolkit.isoutput(s), setdiff(all_funcs, state_vars))
212212
params = ModelingToolkit.parameters(de)
213-
t = ModelingToolkit.arguments(diff_eqs[1].lhs)[1]
213+
t = ModelingToolkit.arguments(clean_calls([diff_eqs[1].lhs])[1])[1]
214+
# very long if in order to avoid duplication
214215
params_from_measured_quantities = union(
215-
[filter(s -> !iscall(s), get_variables(y[2])) for y in measured_quantities]...,
216+
[
217+
filter(
218+
s ->
219+
!iscall(s) &&
220+
!(string(s) in string.(state_vars)) &&
221+
!(string(s) * "(t)" in string.(state_vars)) &&
222+
(string(s) != string(t)),
223+
get_variables(y[2]),
224+
) for y in measured_quantities
225+
]...,
216226
)
217227
params = union(params, params_from_measured_quantities)
218228

src/RationalFunctionFields/RationalFunctionField.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ Output:
149149
mqs_ratfuncs = specialize(IdealMQS(ratfuncs), point; saturated = false)
150150
@assert parent(first(mqs_specialized)) == parent(first(mqs_ratfuncs))
151151
@debug "Starting the groebner basis computation"
152-
gb = groebner(mqs_specialized, loglevel = _groebner_loglevel[])
153-
result = map(iszero, normalform(gb, mqs_ratfuncs, loglevel = _groebner_loglevel[]))
152+
gb = groebner(mqs_specialized)
153+
result = map(iszero, normalform(gb, mqs_ratfuncs))
154154
return result
155155
end
156156

@@ -256,8 +256,8 @@ end
256256
polys_specialized =
257257
ParamPunPam.specialize_mod_p(mqs_tobereduced, point, saturated = false)
258258
@assert parent(first(gens_specialized)) == parent(first(polys_specialized))
259-
gb = groebner(gens_specialized, loglevel = _groebner_loglevel[])
260-
nf = normalform(gb, polys_specialized, loglevel = _groebner_loglevel[])
259+
gb = groebner(gens_specialized)
260+
nf = normalform(gb, polys_specialized)
261261
result = map(iszero, nf)
262262
return result
263263
end

src/RationalFunctionFields/normalforms.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function local_normal_forms(
5656
@assert parent(first(point)) == finite_field
5757
point_ff_ext = append_at_index(point, mqs.sat_var_index, one(finite_field))
5858
gens_ff_spec = specialize_mod_p(mqs, point)
59-
gb_ff_spec = Groebner.groebner(gens_ff_spec, loglevel = _groebner_loglevel[])
59+
gb_ff_spec = Groebner.groebner(gens_ff_spec)
6060
ring_ff = parent(gb_ff_spec[1])
6161
xs_ff = gens(ring_ff)
6262
normal_forms_ff = Vector{elem_type(ring_ff)}(undef, 0)

src/logging.jl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ else
2929
Ref{Logging.ConsoleLogger}(Logging.ConsoleLogger(stderr, Logging.Info))
3030
end
3131

32-
const _groebner_loglevel = Ref{Int}(0)
33-
3432
function restart_logging(; loglevel = Logging.Info)
3533
@assert loglevel isa Base.CoreLogging.LogLevel
3634
_si_logger[] = @static if VERSION >= v"1.7.0"
@@ -41,13 +39,6 @@ function restart_logging(; loglevel = Logging.Info)
4139
for r in _runtime_rubrics
4240
_runtime_logger[r] = 0
4341
end
44-
if loglevel < Logging.Info
45-
_groebner_loglevel[] = 0
46-
elseif loglevel < Logging.Warn
47-
_groebner_loglevel[] = 0
48-
else
49-
_groebner_loglevel[] = 10
50-
end
5142
return nothing
5243
end
5344

src/parametrizations.jl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,7 @@ $sat_string
218218
$tagged_mqs
219219
Monom ordering:
220220
$(ord)"""
221-
tagged_mqs_gb = groebner(
222-
tagged_mqs,
223-
ordering = ord,
224-
homogenize = :no,
225-
loglevel = _groebner_loglevel[],
226-
)
221+
tagged_mqs_gb = groebner(tagged_mqs, ordering = ord, homogenize = :no)
227222
# Relations between tags in K[T]
228223
relations_between_tags = filter(
229224
poly -> isempty(intersect(vars(poly), vcat(sat_var, orig_vars))),

src/power_series_utils.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,7 @@ function ps_ode_solution(
239239
Svconst = AbstractAlgebra.matrix_space(base_ring(ring), n, 1)
240240
eqs = Sv(equations)
241241

242-
x_vars = filter(v -> ("$(v)_dot" in map(string, gens(ring))), gens(ring))
243-
x_vars = [x for x in x_vars]
242+
x_vars = collect(filter(v -> ("$(v)_dot" in map(var_to_str, gens(ring))), gens(ring)))
244243
x_dot_vars = [str_to_var(var_to_str(x) * "_dot", ring) for x in x_vars]
245244

246245
Jac_dots = S([derivative(p, xd) for p in equations, xd in x_dot_vars])
@@ -267,7 +266,7 @@ function ps_ode_solution(
267266
set_precision!(solution[x_vars[i]], new_prec)
268267
set_precision!(solution[x_dot_vars[i]], new_prec)
269268
end
270-
eval_point = [solution[v] for v in gens(ring)]
269+
eval_point = [copy(solution[v]) for v in gens(ring)]
271270
map(ps -> set_precision!(ps, 2 * cur_prec), eval_point)
272271
eqs_eval = map(p -> evaluate(p, eval_point), eqs)
273272
J_eval = map(p -> evaluate(p, eval_point), Jac_xs)

src/primality_check.jl

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,44 @@
1+
# ------------------------------------------------------------------------------
2+
# adapted from https://gitlab.inria.fr/newrur/code/-/blob/main/Julia/RationalUnivariateRepresentation.jl/src/RationalUnivariateRepresentation.jl?ref_type=heads#L180
3+
# thanks to Alexander Demin
4+
"""
5+
quotient_basis(J::Array{QQMPolyRingElem, 1})
6+
7+
Takes as input a Groebner basis J of a zero-dimensional ideal and
8+
returns a monomial basis of the quotient ring
9+
(more precisely, the list of standard monomials)
10+
"""
11+
function quotient_basis(J::Array{<:MPolyRingElem, 1})
12+
if !Groebner.isgroebner(J)
13+
throw(DomainError("Input is not a Groebner basis"))
14+
end
15+
n = length(gens(parent(first(J))))
16+
leading_exponents = [first(Nemo.exponent_vectors(Nemo.leading_monomial(p))) for p in J]
17+
exponents_to_check = [[0 for _ in 1:n]]
18+
exponents_checked = []
19+
basis_exponents = []
20+
while length(exponents_to_check) > 0
21+
e = popfirst!(exponents_to_check)
22+
push!(exponents_checked, e)
23+
if !any(map(le -> all(e .>= le), leading_exponents))
24+
push!(basis_exponents, e)
25+
for i in 1:n
26+
next_e = copy(e)
27+
next_e[i] += 1
28+
if !(next_e in exponents_checked) && !(next_e in exponents_to_check)
29+
push!(exponents_to_check, next_e)
30+
end
31+
end
32+
end
33+
end
34+
return [prod(gens(parent(first(J))) .^ e) for e in basis_exponents]
35+
end
36+
137
# ------------------------------------------------------------------------------
238

339
function check_primality_zerodim(J::Array{QQMPolyRingElem, 1})
4-
J = Groebner.groebner(J, loglevel = _groebner_loglevel[])
5-
basis = Groebner.kbase(J, loglevel = _groebner_loglevel[])
40+
J = Groebner.groebner(J)
41+
basis = quotient_basis(J)
642
dim = length(basis)
743
S = Nemo.matrix_space(Nemo.QQ, dim, dim)
844
matrices = []
@@ -11,7 +47,7 @@ function check_primality_zerodim(J::Array{QQMPolyRingElem, 1})
1147
for v in gens(parent(first(J)))
1248
M = zero(S)
1349
for (i, vec) in enumerate(basis)
14-
image = Groebner.normalform(J, v * vec, loglevel = _groebner_loglevel[])
50+
image = Groebner.normalform(J, v * vec)
1551
for (j, base_vec) in enumerate(basis)
1652
M[i, j] = Nemo.QQ(coeff(image, base_vec))
1753
end

src/wronskian.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ Computes the Wronskians of io_equations
237237

238238
@debug "Constructing Wronskians"
239239
result = []
240-
for (i, tlist) in enumerate(termlists)
240+
for tlist in termlists
241241
n = length(tlist)
242242
evaled = massive_eval(tlist, ps_ext)
243243
S = Nemo.matrix_space(F, n, n)

test/differentiate_output.jl

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function diff_sol_Lie_derivatives(ode::ODE, params, ic, inputs, prec::Int)
6464
push!(
6565
result[y][v],
6666
eval_at_dict(
67-
derivative(Lie_derivatives[y][j], str_to_var("$v", new_ring)),
67+
derivative(Lie_derivatives[y][j], switch_ring(v, new_ring)),
6868
eval_point,
6969
),
7070
)
@@ -123,6 +123,57 @@ end
123123
),
124124
)
125125

126+
ode = @ODEmodel(
127+
x'(t) = x(t)^2 + 2 * x(t) * y(t) - 3 * a * y(t),
128+
y'(t) = x(t)^2 + a * b - b^2 + 4 * b * x(t),
129+
y1(t) = a * x(t),
130+
y2(t) = b * y(t)^2 - y(t)
131+
)
132+
push!(
133+
test_cases,
134+
Dict(
135+
:ODE => ode,
136+
:ic => Dict(x => Nemo.QQ(rand(1:10)), y => Nemo.QQ(rand(1:10))),
137+
:param_vals => Dict(a => Nemo.QQ(rand(1:10)), b => Nemo.QQ(rand(1:10))),
138+
:inputs => Dict{P, Array{QQFieldElem, 1}}(),
139+
:prec => 7,
140+
),
141+
)
142+
143+
ode = @ODEmodel(
144+
x'(t) = x(t)^2 + 2 * x(t) * y(t) - 3 * a * y(t),
145+
y'(t) = x(t)^2 + a * b - b^2 + 4 * b * x(t),
146+
y1(t) = a * x(t),
147+
y2(t) = b * y(t)^2 - y(t)
148+
)
149+
push!(
150+
test_cases,
151+
Dict(
152+
:ODE => ode,
153+
:ic => Dict(x => Nemo.QQ(rand(1:10)), y => Nemo.QQ(rand(1:10))),
154+
:param_vals => Dict(a => Nemo.QQ(rand(1:10)), b => Nemo.QQ(rand(1:10))),
155+
:inputs => Dict{P, Array{QQFieldElem, 1}}(),
156+
:prec => 9,
157+
),
158+
)
159+
160+
ode = @ODEmodel(
161+
x'(t) = x(t)^2 + 2 * x(t) * y(t) - 3 * a * y(t),
162+
y'(t) = x(t)^2 + a * b - b^2 + 4 * b * x(t),
163+
y1(t) = a * x(t),
164+
y2(t) = b * y(t)^2 - y(t)
165+
)
166+
push!(
167+
test_cases,
168+
Dict(
169+
:ODE => ode,
170+
:ic => Dict(x => Nemo.QQ(rand(1:10)), y => Nemo.QQ(rand(1:10))),
171+
:param_vals => Dict(a => Nemo.QQ(rand(1:10)), b => Nemo.QQ(rand(1:10))),
172+
:inputs => Dict{P, Array{QQFieldElem, 1}}(),
173+
:prec => 3,
174+
),
175+
)
176+
126177
ode = @ODEmodel(x'(t) = u(t) + a, y(t) = x(t))
127178
push!(
128179
test_cases,
@@ -161,6 +212,7 @@ end
161212
),
162213
)
163214

215+
t = copy(test_cases)
164216
varnames = vcat(
165217
["x_$i" for i in 1:3],
166218
["p_$i" for i in 1:3],
@@ -201,8 +253,40 @@ end
201253
:prec => 4,
202254
),
203255
)
256+
push!(
257+
test_cases,
258+
Dict(
259+
:ODE => ODE{P}(
260+
Dict{P, DType}(
261+
vars[i] => rand_poly(1, vars[1:5]) // (vars[1] + vars[3]) for i in 1:2
262+
),
263+
Dict{P, DType}(vars[i] => rand_poly(1, vars[1:5]) for i in 6:7),
264+
[vars[5]],
265+
),
266+
:ic => Dict(vars[i] => F(rand(1:50)) for i in 1:2),
267+
:param_vals => Dict(vars[i + 2] => F(rand(1:50)) for i in 1:2),
268+
:inputs => Dict(vars[5] => [F(rand(-30:30)) for i in 1:4]),
269+
:prec => 3,
270+
),
271+
)
272+
push!(
273+
test_cases,
274+
Dict(
275+
:ODE => ODE{P}(
276+
Dict{P, DType}(
277+
vars[i] => rand_poly(1, vars[1:5]) // (vars[1] + vars[3]) for i in 1:2
278+
),
279+
Dict{P, DType}(vars[i] => rand_poly(1, vars[1:5]) for i in 6:7),
280+
[vars[5]],
281+
),
282+
:ic => Dict(vars[i] => F(rand(1:50)) for i in 1:2),
283+
:param_vals => Dict(vars[i + 2] => F(rand(1:50)) for i in 1:2),
284+
:inputs => Dict(vars[5] => [F(rand(-30:30)) for i in 1:5]),
285+
:prec => 5,
286+
),
287+
)
204288

205-
for case in test_cases
289+
for case in t
206290
ode, prec = case[:ODE], case[:prec]
207291
@time sol1 =
208292
differentiate_output(ode, case[:param_vals], case[:ic], case[:inputs], prec)

test/runtests.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ using StructuralIdentifiability:
6565
y_vars,
6666
x_equations,
6767
y_equations,
68-
inputs
68+
inputs,
69+
quotient_basis
6970

7071
const GROUP = get(ENV, "GROUP", "All")
7172

0 commit comments

Comments
 (0)