Gröbner Bases for Polynomial Ideals and Applications

Authors: Christian Eder, Rafael Mohr and Mohab Safey El Din

This page contains the code samples from the corresponding chapter in the OSCAR book. You can access the full chapter here.

How to use Gröbner bases in OSCAR explained on the computation of Hilbert series

julia> R, (X0, X1, X2, X3) = graded_polynomial_ring(QQ, ["X$i" for i in 0:3]);

julia> I = ideal(R, [X0*X2 - X1^2, X1*X3 - X2^2, X0*X3 - X1*X2]);

julia> A, _ = quo(R, I);

julia> hilbert_series(A)
(2*t^3 - 3*t^2 + 1, (-t + 1)^4)

julia> p = next_prime(rand(1:10000))
4783

julia> R, (X0, X1, X2, X3) = graded_polynomial_ring(GF(p), ["X$i" for i in 0:3]);

julia> I = ideal(R, [X0*X2 - X1^2, X1*X3 - X2^2, X0*X3 - X1*X2]);

julia> gb = groebner_basis_f4(forget_grading(I));

julia> lm_ideal = ideal(R, (leading_monomial).(gens(gb)));

julia> A, _ = quo(R, lm_ideal);

julia> hilbert_series(A)
(2*t^3 - 3*t^2 + 1, (-t + 1)^4)

Computing Gröbner bases with respect to different monomial orderings

Applying elimination

julia> R, (x, y, z) = polynomial_ring(QQ, ["x","y","z"]);

julia> o = degrevlex([x, y])*degrevlex([z]);

julia> I = ideal(R, [x^2 + y + z - 1, x + y^2 + z - 1, x + y + z^2 - 1]);

julia> groebner_basis(I, ordering = o)
Gröbner basis with elements
  1: z^6 - 4*z^4 + 4*z^3 - z^2
  2: 2*y*z^2 + z^4 - z^2
  3: x + y + z^2 - 1
  4: y^2 + x + z - 1
with respect to the ordering
  degrevlex([x, y])*degrevlex([z])

julia> eliminate(I, [x,y]) # internally computes the above Gröbner basis
Ideal generated by
  z^6 - 4*z^4 + 4*z^3 - z^2

julia> groebner_basis(I)
Gröbner basis with elements
  1: z^2 + x + y - 1
  2: y^2 + x + z - 1
  3: x^2 + y + z - 1
with respect to the ordering
  degrevlex([x, y, z])

Using the FGLM algorithm for a change of ordering

julia> R, (x1, x2, x3, x4, x5, x6, x7, x8) = polynomial_ring(GF(65521), ["x1","x2","x3","x4","x5","x6", "x7","x8"]);

julia> I = ideal(R, [x1 + 2*x2 + 2*x3 + 2*x4 + 2*x5 + 2*x6 + 2*x7 + 2*x8 - 1, x1^2 - x1 + 2*x2^2 + 2*x3^2 + 2*x4^2 + 2*x5^2 + 2*x6^2 + 2*x7^2 + 2*x8^2, 2*x1*x2 + 2*x2*x3 - x2 + 2*x3*x4 + 2*x4*x5 + 2*x5*x6 + 2*x6*x7 + 2*x7*x8, 2*x1*x3 + x2^2 + 2*x2*x4 + 2*x3*x5 - x3 + 2*x4*x6 + 2*x5*x7 + 2*x6*x8, 2*x1*x4 + 2*x2*x3 + 2*x2*x5 + 2*x3*x6 + 2*x4*x7 - x4 + 2*x5*x8, 2*x1*x5 + 2*x2*x4 + 2*x2*x6 + x3^2 + 2*x3*x7 + 2*x4*x8 - x5, 2*x1*x6 + 2*x2*x5 + 2*x2*x7 + 2*x3*x4 + 2*x3*x8 - x6, 2*x1*x7 + 2*x2*x6 + 2*x2*x8 + 2*x3*x5 + x4^2 - x7]);

julia> @time groebner_basis_f4(I);
  0.010955 seconds (57.13 k allocations: 3.081 MiB)

julia> dim(I) == 0
true

julia> @time fglm(I, destination_ordering = lex(R));
  0.062046 seconds (130.52 k allocations: 3.313 MiB)

Compute real solutions

julia> R, (t1, t2) = polynomial_ring(QQ, ["t1", "t2"]);

julia> psi = [rand(R, 6:6, 3:5, -10:10) for _ in 1:3]
3-element Vector{QQMPolyRingElem}:
 1//2*t1^5*t2^3 - 2*t1^3*t2^4 + 2//9*t1^3*t2^3
 -3//5*t1^5*t2^5 - 8//7*t1^3*t2^4 - 17//4*t1^3*t2^3
 -23//12*t1^5*t2^5 - 3//7*t1^4*t2^3 - 13//6*t1^3*t2^5 - 9*t1^3*t2^4

julia> D = sum([(f - rand(Int))^2 for f in psi]);

julia> J = jacobian_ideal(D);

julia> S, (t1, t2, s) = polynomial_ring(QQ, ["t1", "t2", "s"]);

julia> phi = hom(R, S, [t1, t2]);

julia> f = sum([rand(Int) * p for p in minors(jacobian_matrix(psi), 2)]);

julia> JJ = phi(J) + ideal(S, s*phi(f) - 1);

julia> sols, param = real_solutions(JJ);

julia> length(sols)
8

julia> degree(param.elim)
62

Computing non-proper points

julia> R, (x, y, z, t) = polynomial_ring(QQ, ["x", "y", "z", "t"]);

julia> graph_id = ideal(R, [x*y, x*z, y*z, x*(x-1), x-t]);

julia> w = [1 1 1 0]
1×4 Matrix{Int64}:
 1  1  1  0

julia> H = homogenizer(R, w, "w"); clo = H(graph_id)
Ideal generated by
  -x + t*w
  t^2 - t
  z*t
  y*t
  x*t - x
  y*z
  x*z
  x*y
  x^2 - x*w

julia> S = base_ring(clo)
Multivariate polynomial ring in 5 variables over QQ graded by
  x -> [1]
  y -> [1]
  z -> [1]
  t -> [0]
  w -> [1]

julia> x, y, z, t, w = gens(S);

julia> irrel_ideal = ideal(S, [x,y,z,w]);

julia> eliminate(saturation(clo + ideal(S,x), irrel_ideal), [x,y,z,w])
Ideal generated by
  t

julia> eliminate(saturation(clo + ideal(S,y), irrel_ideal), [x,y,z,w])
Ideal generated by
  t^2 - t

julia> eliminate(saturation(clo + ideal(S,z), irrel_ideal), [x,y,z,w])
Ideal generated by
  t^2 - t

julia> eliminate(saturation(clo + ideal(S,w), irrel_ideal), [x,y,z,w])
Ideal generated by
  t

Computing conormal spaces and Whitney stratifications

julia> R, (x, y, z, w) = graded_polynomial_ring(QQ, ["x","y","z","w"]);

julia> f = y^2*w^2 + z^3*w - x^2*z^2;

julia> J = jacobian_matrix(f)
[          -2*x*z^2]
[           2*y*w^2]
[-2*x^2*z + 3*z^2*w]
[     2*y^2*w + z^3]

julia> I_sing = ideal(R, [f, minors(J, 1)...])
Ideal generated by
  -x^2*z^2 + y^2*w^2 + z^3*w
  -2*x*z^2
  2*y*w^2
  -2*x^2*z + 3*z^2*w
  2*y^2*w + z^3

julia> minimal_primes(I_sing)
2-element Vector{MPolyIdeal{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}:
 Ideal (w, z)
 Ideal (z, y)

julia> (comp -> comp[2]).(primary_decomposition(I_sing))
6-element Vector{MPolyIdeal{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}:
 Ideal (w, z)
 Ideal (z, y)
 Ideal (w, z, y)
 Ideal (w, z, x)
 Ideal (z, y, x)
 Ideal (x, y, z, w)

julia> R, (x0,x1,x2,x3,a0,a1,a2,a3) = polynomial_ring(QQ, ["x0","x1","x2","x3","a0","a1","a2","a3"]);

julia> f = x0^6 + x0^4*x1*x2 + x2^3*x3^3;

julia> J = jacobian_matrix(f)[1:4, 1:1]
[6*x0^5 + 4*x0^3*x1*x2]
[              x0^4*x2]
[x0^4*x1 + 3*x2^2*x3^3]
[          3*x2^3*x3^2]

julia> JJ = hcat(J, R[a0; a1; a2; a3])
[6*x0^5 + 4*x0^3*x1*x2   a0]
[              x0^4*x2   a1]
[x0^4*x1 + 3*x2^2*x3^3   a2]
[          3*x2^3*x3^2   a3]

julia> id = ideal(R, minors(JJ, 2));

julia> I_sing = ideal(R, minors(J, 1));

julia> conorm = saturation(ideal(R, f) + id, I_sing);

julia> Y = radical(ideal(R,f) + I_sing)
Ideal generated by
  x0
  x2*x3

julia> id_fib_Y = saturation(conorm + Y, ideal(R, [x0,x1,x2,x3]));

julia> prim_comps = (comp -> comp[2]).(primary_decomposition(id_fib_Y));

julia> [eliminate(comp, [a0,a1,a2,a3]) for comp in prim_comps]
6-element Vector{MPolyIdeal{QQMPolyRingElem}}:
 Ideal (x2, x0)
 Ideal (x3, x2, x0)
 Ideal (x3, x0)
 Ideal (x3, x2, x0)
 Ideal (x3, x1, x0)
 Ideal (x2, x0, 4*x1^3 + 27*x3^3)

An example from combinatorics

julia> F = GF(rand_bits_prime(ZZ, 20))
Prime field of characteristic 646637

julia> R, (z0, z1, z2, t, u, x) = polynomial_ring(F, ["z0","z1","z2","t", "u","x"]);

julia> P = (u^3-t*(u^7+1))*x-u^3+t*z0+t*u*z1+inv(F(2))*t*u^2*z2;

julia> sys = [P,derivative(P,u),derivative(P,x)];

julia> I = saturation(ideal(R, sys), ideal(R, u));

julia> I = eliminate(ideal(R, sys), [x]);

julia> sys[3]
646636*t*u^7 + 646636*t + u^3

julia> S, (z0, z1, z2, t, u, u1, u2, x) = polynomial_ring(F, ["z0","z1","z2","t","u","u1","u2","x"]);

julia> phi = hom(R,S,[z0,z1,z2,t,u,x]);

julia> I = phi(I);

julia> I += ideal(S, [f(z0,z1,z2,t,u1,u1,u2,x) for f in gens(I)]);

julia> I += ideal(S, [f(z0,z1,z2,t,u2,u1,u2,x) for f in gens(I)]);

julia> I = saturation(I,ideal(S,(u-u1)*(u1-u2)*(u-u2)));

julia> res = eliminate(I, [z1,z2,u,u1,u2,x]);

julia> factor(first(gens(res)))
1 * (z0^35*t^35 + 646636*z0^31*t^28 + z0^30*t^28 + 646636*z0^29*t^28 + 5*z0^28*t^28 + 646636*z0^25*t^21 + z0^24*t^21 + 3*z0^23*t^21 + 646633*z0^22*t^21 + 10*z0^21*t^21 + z0^19*t^14 + 646636*z0^18*t^14 + 5*z0^17*t^14 + 3*z0^16*t^14 + 646631*z0^15*t^14 + 10*z0^14*t^14 + z0^13*t^7 + 646636*z0^12*t^7 + 3*z0^10*t^7 + z0^9*t^7 + 646633*z0^8*t^7 + 5*z0^7*t^7 + 646636*z0 + 1)

Checking for local complete intersections

julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);

julia> I = ideal(R, [x*y, x*z, y*z]);

julia> conorm = subquotient(matrix(gens(I)), matrix(gens(I^2)))
Subquotient of submodule with 3 generators
  1: x*y*e[1]
  2: x*z*e[1]
  3: y*z*e[1]
by submodule with 6 generators
  1: x^2*y^2*e[1]
  2: x^2*y*z*e[1]
  3: x*y^2*z*e[1]
  4: x^2*z^2*e[1]
  5: x*y*z^2*e[1]
  6: y^2*z^2*e[1]

julia> fitting_ideal(conorm, 1)
Ideal generated by
  y*z
  x*z
  x*y

julia> fitting_ideal(conorm, 2)
Ideal generated by
  z
  y
  x

julia> equidimensional_decomposition_weak(I)
1-element Vector{MPolyIdeal{QQMPolyRingElem}}:
 Ideal (x*y, x*z, y*z)

julia> F = fitting_ideal(ideal_as_module(I), 2);

julia> codim(F) >= codim(I) + 1
true

julia> I1 = ideal(R, [x-1, y-1]);

julia> I2 = ideal(R, [x, y, z]);

julia> I = intersect(I1, I2);

julia> conorm = subquotient(matrix(gens(I)), matrix(gens(I^2)));

julia> Pk(conorm, k) = saturation(I, fitting_ideal(conorm, k)) + fitting_ideal(conorm, k-1);

julia> Pk(conorm, 2) == ideal(R, [x-1,y-1])
true

julia> Pk(conorm, 3) == ideal(R, [z,y,x])
true
Edit this page Contact Imprint Privacy policy © 2018-2025 The OSCAR Team