This is an (experimental) implementation of some methods of computer algebra in Haskell, in particular for the computation of Gröbner bases.
The ComputerAlgebra library provides the type classes Ring, Algebra
and RingWithDiv to represent the corresponding mathematical objects.
The RR type represents the real numbers and is essentially a small wrapper
around Double, viewed as a ring.
Similarly, QQ represents the rationals and ZZ the integers.
Monomial orders are represented by the MonOrder data type.
The following monomial orders are provided:
lexi_order: the lexicographic ordergraded_lexi_order: the graded lexicographic ordergrevlex_order: the graded reverse lexicographic order
Then one can construct graded polynomials as follows:
import ComputerAlgebra
-- The polynomial x^2 + 2xy + 3 y^2 with the lexicographic order x > y.
f_1 :: OrderedPolynomial RR
f_1 = make_ordered_poly (lexi_order [1,2]) [([2,0], RR 1), ([1,1], RR 2), ([0,2], RR 3)]
-- The polynomial y^2 + x^2 with the lexicographic order y > x.
f_2 :: OrderedPolynomial RR
f_2 = make_ordered_poly (lexi_order [2,1]) [([0,2], RR 1), ([2,0], RR 1)]
-- The polynomial xy with the lexicographic order y > x.
f_3 :: OrderedPolynomial RR
f_3 = make_ordered_poly (lexi_order [2,1]) [([1,1], RR 1)]Using the GroebnerBases module, we can then use the function buchberger_algorithm
to compute a Gröbner basis.
Similarly, the compute_reduced_groebner_basis computes the (unique) reduced Gröbner basis.
import GroebnerBases
ex_1 = make_ordered_poly (lexi_order [3,2,1]) [([0,0,2], QQ (-1)), ([0,2,0], QQ (-2)), ([0,1,0], QQ 1), ([1,0,0], QQ 2)]
ex_2 = make_ordered_poly (lexi_order [3,2,1]) [([0,0,2], QQ 1), ([0,2,0], QQ (-1)), ([1,0,0], QQ 1)]
ex_3 = make_ordered_poly (lexi_order [3,2,1]) [([0,0,2], QQ (-1)), ([1,1,0], QQ 1)]
buchberger_algorithm [ex_1, ex_2, ex_3]
compute_reduced_groebner_basis [ex_1, ex_2, ex_3]For example, we can use this to check that the order of the polynomials w.r.t. which which the reduction takes place matters. Defining
e = make_ordered_poly (lexi_order [1,2]) [([1,1], RR 1), ([0,1], RR 1)]
e_1 = make_ordered_poly (lexi_order [1,2]) [([1,0], RR 1), ([0,0], RR 1)]
e_2 = make_ordered_poly (lexi_order [1,2]) [([1,0], RR 1)]and running
compute_normal_form [e_1,e_2] e
compute_normal_form [e_2,e_1] eyields 0 and x₂, respectively.
We can also compute S-polynomials:
spol f_2 f_3