In this section we will describe step 6 of Algorithm 1, i.e., our verified implementation of Berlekamp’s Algorithm to factor square-free polynomials in \(\mathrm {GF}(p)\).
Informal Description
Algorithm 2 briefly describes Berlekamp’s algorithm [5]. It focuses on the core computations that have to be performed. For a discussion on why these steps are performed we refer to Knuth [18, Sect. 4.6.2].
We illustrate the algorithm by continuing Example 2.
Example 3
In Algorithm 1, step 6, we have to factor f in \(\mathrm {GF}(7)[x]\). To this end, we first simplify f by
$$\begin{aligned} f \equiv 4 + 5x + 5x^2 + 5x^3 + 4x^4 + 3x^5 \quad (mod 7) \end{aligned}$$
before passing it to Berlekamp’s algorithm.
Step 1 now divides this polynomial by its leading coefficient \(c = 3\) in \(\mathrm {GF}(7)\) and obtains the new \(f:= 6 + 4x + 4x^2 + 4x^3 + 6x^4 + x^5\).
Step 2 computes the Berlekamp matrix as
$$\begin{aligned} B_f = \left( \begin{array}{ccccc} 1 &{}\quad 0 &{}\quad 0 &{}\quad 0 &{}\quad 0 \\ 4 &{} \quad 6 &{}\quad 2 &{}\quad 4 &{} \quad 3 \\ 2 &{}\quad 3 &{}\quad 6 &{}\quad 1 &{}\quad 4 \\ 6 &{}\quad 3 &{}\quad 5 &{}\quad 3 &{}\quad 1 \\ 1 &{}\quad 5 &{}\quad 5 &{}\quad 6 &{}\quad 6 \end{array}\right) \end{aligned}$$
since
$$\begin{aligned} \begin{array}{rcll} x^0 \mathbin {mod }f &{} \equiv &{} 1 &{}(mod 7) \\ x^7 \mathbin {mod }f &{} \equiv &{} 4 + 6x + 2x^2 + 4x^3 + 3x^4 &{}(mod 7) \\ x^{14} \mathbin {mod }f &{} \equiv &{} 2 + 3x + 6x^2 + x^3 + 4x^4 &{}(mod 7) \\ x^{21} \mathbin {mod }f &{} \equiv &{} 6 + 3x + 5x^2 + 3x^3 + x^4 &{}(mod 7) \\ x^{28} \mathbin {mod }f &{} \equiv &{} 1 + 5x + 5x^2 + 6x^3 + 6x^4 &{}(mod 7). \end{array} \end{aligned}$$
Step 3 computes a basis of the left null space of \(B_f - I\), e.g., by applying the Gauss–Jordan elimination to its transpose \((B_f -I)^\mathrm {T}\):
$$\begin{aligned} \left( \begin{matrix} 0&{}\quad 0&{}\quad 0&{}\quad 0&{}\quad 0\\ 4&{}\quad 5&{}\quad 2&{}\quad 4&{}\quad 3\\ 2&{}\quad 3&{}\quad 5&{}\quad 1&{}\quad 4\\ 6&{}\quad 3&{}\quad 5&{}\quad 2&{}\quad 1\\ 1&{}\quad 5&{}\quad 5&{}\quad 6&{}\quad 5 \end{matrix}\right) ^{\!\!\mathrm {T}} = \left( \begin{array}{ccccc} 0 &{}\quad 4 &{}\quad 2 &{}\quad 6 &{}\quad 1 \\ 0 &{}\quad 5 &{}\quad 3 &{}\quad 3 &{}\quad 5 \\ 0 &{}\quad 2 &{}\quad 5 &{}\quad 5 &{}\quad 5 \\ 0 &{}\quad 4 &{}\quad 1 &{}\quad 2 &{}\quad 6 \\ 0 &{}\quad 3 &{}\quad 4 &{}\quad 1 &{}\quad 5 \end{array}\right) \hookrightarrow \left( \begin{array}{ccccc} 0 &{}\quad 1 &{}\quad 0 &{}\quad 0 &{}\quad 2 \\ 0 &{}\quad 0 &{}\quad 1 &{}\quad 0 &{}\quad 1 \\ 0 &{}\quad 0 &{}\quad 0 &{}\quad 1 &{}\quad 2 \\ 0 &{}\quad 0 &{}\quad 0 &{}\quad 0 &{}\quad 0 \\ 0 &{}\quad 0 &{}\quad 0 &{}\quad 0 &{}\quad 0 \end{array}\right) \end{aligned}$$
We determine \(r = 2\), and extract the basis vectors \(b_1 = (1\ 0\ 0\ 0\ 0)\) and \(b_2 = (0\ 5\ 6\ 5\ 1)\). Step 4 converts them into the polynomials \(h_1 = 1\) and \(h_2 = 5x + 6x^2 + 5x^3 + x^4\), and step 5 initializes \(H = \{h_2\}\), \(F = \{f\}\), and \(F_I = \emptyset \).
The termination condition in step 6 does not hold. So in step 7 we pick \(h = h_2\) and compute the required GCD s.
$$\begin{aligned} \gcd (f, h_2 - 1)&= 6 + 5x + 6x^2 + 5x^3 + x^4 =: f_1\\ \gcd (f, h_2 - 4)&= 1 + x =: f_2\\ \gcd (f, h_2 - i)&= 1 \qquad \qquad \text {for all }i \in \{0,2,3,5,6\} \end{aligned}$$
Afterwards, we update \(F := \{f_1,f_2\}\) and \(H := \emptyset \).
Step 8 is just an optimization. For instance, in our implementation we move all linear polynomials from F into \(F_I\), so that in consecutive iterations they do not have to be tested for further splitting in step 7. Hence, step 8 updates \(F_I := \{f_2\}\), \(F := \{f_1\}\), and \(r := 1\).
Now we go back to step 6, where both termination criteria fire at the same time (\(|F| = 1 = r \wedge H = \emptyset \)). We return \(c \cdot f_1 \cdot f_2\) as final factorization, i.e.,
$$\begin{aligned} f \equiv 3 \cdot (1 + x) \cdot (6 + 5x + 6x^2 + 5x^3 + x^4) \quad (mod 7) \end{aligned}$$
All of the arithmetic operations in Algorithm 2 have to be performed in the prime field \(\mathrm {GF}(p)\). Hence, in order to implement Berlekamp’s algorithm, we basically need the following operations: arithmetic in \(\mathrm {GF}(p)\), polynomials over \(\mathrm {GF}(p)\), the Gauss–Jordan elimination over \(\mathrm {GF}(p)\), and GCD-computation for polynomials over \(\mathrm {GF}(p)\).
Soundness of Berlekamp’s Algorithm
Our soundness proof for Berlekamp’s algorithm is mostly based on the description in Knuth’s book.
We first formalize the equations (7, 8, 9, 10, 13, 14) in the textbook [18, p. 440 and 441]. To this end, we also adapt existing proofs from the Isabelle distribution and the AFP; for instance, to derive (7) in the textbook, we adapted a formalization of the Chinese remainder theorem, which we could find only for integers and naturals, to be applicable to polynomials over fields. For another example, (13) uses the equality \((f + g)^p = f^p + g^p\) where f and g are polynomials over \(\mathrm {GF}(p)\), which we prove using some properties about binomial coefficients that were missing in the library. Having proved these equations, we eventually show that after step 3 of Algorithm 2, we have a basis \(b_1,\dots ,b_r\) of the left null space of \(B_f - I\).
Now, step 4 transforms the basis into polynomials. We define an isomorphism between the left null space of \(B_f - I\) and the Berlekamp subspace
so that the isomorphism transforms the basis \(b_1,\dots ,b_r\) into a Berlekamp basis\(H_b := \{h_1,\dots ,h_r\}\), a basis of \(W_f\). Then we prove that every factorization of f has at most r factors.
In this proof we do not follow Knuth’s arguments, but formalize our own version of the proof to reuse some results which we have already proved in the development. Our proof is based on another isomorphism between the vector spaces \(W_f\) and \(\mathrm {GF}(p)^r\) as well as the use of the Chinese remainder theorem over polynomials and the uniqueness of the solution.
Lemma 16
Every factorization of a square-free monic polynomial \(f \in \mathrm {GF}(p)[x]\) has at most \(\dim W_f\) factors.
Proof
Let \(f \equiv f_1 \cdot \ldots \cdot f_r \quad (mod p)\) be a monic irreducible factorization in \(\mathrm {GF}(p)[x]\), which exists and is unique up to permutation since \(\mathrm {GF}(p)[x]\) is a unique factorization domain. We show that there exists an isomorphism between the vector spaces \(W_f\) and \(\mathrm {GF}(p)^r\). Then they have the same dimension and thus every factorization of f has at most \(\dim W_f = \dim \mathrm {GF}(p)^r = r\) factors, which is the desired result.
First, the following equation holds for any polynomial \(g \in W_f\). It corresponds to equation (10) in the textbook [18, p. 440].
$$\begin{aligned} g^p - g\ = \prod _{a \in \mathrm {GF}(p)} (g - a). \end{aligned}$$
(10)
From this we infer that each \(f_i\) divides \(\prod _{a \in \mathrm {GF}(p)}(g - a)\). Since \(f_i\) is irreducible, \(f_i\) divides \(g-a\) for some \(a \in \mathrm {GF}(p)\) and thus, \((g \mathbin {mod }f_i) = -a\) is a constant.
Now we define the desired isomorphism \(\phi \) between \(W_f\) and \(\mathrm {GF}(p)^r\) as follows:
$$\begin{aligned} \phi :&W_f \rightarrow \mathrm {GF}(p)^r\\&g \mapsto (g \mathbin {mod }f_1, \dots , g \mathbin {mod }f_r) \end{aligned}$$
To show that \(\phi \) is an isomorphism, we start with proving that \(\phi \) is injective. Let us assume that \(\phi \, g = 0\) for some \(g \in W_f\). It is easy to show
and \(\forall i<r.\ g \equiv \phi \, g \quad (mod f_i)\). Since \(v = 0 \in W_f\) satisfies these properties, the uniqueness result of the Chinese remainder theorem guarantees that \(g = 0\). This implies the injectivity of \(\phi \), since any linear map is injective if and only if its kernel is {0} [2, Proposition 3.2].
To show that \(\phi \) is surjective, consider an arbitrary \(x = (x_1, \dots , x_r) \in \mathrm {GF}(p)^r\). We show that there exists a polynomial \(g \in W_f\) such that \(\phi \, g = x\). The Chinese remainder theorem guarantees that there exists a polynomial g such that:
$$\begin{aligned}&\forall i<r.\ g \equiv x_i \quad (mod f_i) \end{aligned}$$
(4)
Then, for each \(i < r\) we have
, and so \(g^{p} \equiv g \quad (mod f_i)\). Since each \(f_i\) is irreducible and f is square-free, we have \(g^p \equiv g \quad (mod \prod f_i)\). As \(\prod f_i = f\), we conclude \(g \in W_f\). Finally, \(\phi \, g = x\) follows from (4) and the fact that \(g \mathbin {mod }f_i\) is a constant. \(\square \)
As expected, the proof in Isabelle requires more details and it takes us about 300 lines (excluding any previous necessary result and the proof of the Chinese remainder theorem). We define a function for indexing the factors, we prove that both \(W_f\) and \(\mathrm {GF}(p)^r\) are finite-dimensional vector spaces and also that \(\phi \) is a linear map. Since each equation of the proof involves polynomials over \(\mathrm {GF}(p)\) (so everything is modulo p), we also proved facts like
and so on. In addition, we also extend an existing AFP entry [22] about vector spaces for some necessary results about linear maps, isomorphisms between vector spaces, dimensions, and bases.
Once having proved that \(H_b\) is a Berlekamp basis for f and that the number of irreducible factors is \(|H_b|\), we prove (14); for every divisor \(f_i\) of f and every \(h \in H_b\), we have
$$\begin{aligned} f_i = \prod _{0 \le j < p} \gcd (f_i, h - j). \end{aligned}$$
(14)
Finally, it follows that every non-constant reducible divisor \(f_i\) of f can be properly factored by \(\gcd (f_i, h - j)\) for suitable \(h \in H_b\) and \(0 \le j < p\).
In order to prove the soundness of steps 5–9 in Algorithm 2, we use the following invariants—these are not stated by Knuth as equations. Here, \(H_{old }\) represents the set of already processed polynomials of \(H_b\).
- 1.
\(f = \prod (F \cup F_I)\).
- 2.
All \(f_i \in F \cup F_I\) are monic and non-constant.
- 3.
All \(f_i \in F_I\) are irreducible.
- 4.
\(H_b = H \cup H_{old }\).
- 5.
\(\gcd (f_i,h - j) \in \{1,f_i\}\) for all \(h \in H_{old }\), \(0 \le j < p\) and \(f_i \in F \cup F_I\).
- 6.
\(|F_I| + r = |H_b|\).
It is easy to see that all invariants are initially established in step 5 by picking \(H_{old } = \{1\} \cap H_b\). In particular, invariant 5 is satisfied since the GCD of the monic polynomial f and a constant polynomial c is either 1 (if \(c\ne 0\)) or f (if \(c=0\)).
It is also not hard to see that step 7 preserves the invariants. In particular, invariant 5 is satisfied for elements in \(F_I\) since these are irreducible. Invariant 1 follows from (14).
The irreducibility of the final factors that are returned in step 6 can be argued as follows. If \(|F| = r\), then by invariant 6 we know that \(|H_b| = |F \cup F_I|\), i.e., \(F \cup F_I\) is a factorization of f with the maximum number of factors, and thus every factor is irreducible. In the other case, \(H = \emptyset \) and hence \(H_{old } = H_b\) by invariant 4. Combining this with invariant 5 shows that every element \(f_i\) in \(F \cup F_I\) cannot be factored by \(\gcd (f_i,h - j)\) for any \(h \in H_b\) and \(0 \le j < p\). Since \(H_b\) is a Berlekamp basis, this means that \(f_i\) must be irreducible.
Putting everything together we arrive at the formalized main soundness statement of Berlekamp’s algorithm. As in Sect. 6.3 we will integrate the distinct-degree factorization [18, p. 447 and 448], the algorithm takes, besides the monic polynomial f to be factored, an extra argument \(d \in {\mathbb {N}}\) such that any degree-d factor of f is known to be irreducible. Fixing \(d=1\) yields the usual Berlekamp’s algorithm. The final statement looks as follows.
Theorem 3
(Berlekamp’s Algorithm for monic polynomials)
In order to prove the validity of the output factorization, we basically use the invariants mentioned before. However, it still requires some tedious reasoning.
Formalizing the Distinct-Degree Factorization Algorithm
The distinct-degree factorization (cf. [18, p. 447 and 448]) is an algorithm that splits a square-free polynomial into (possibly reducible) factors, where irreducible factors of each factor have the same degree. It is commonly used before applying randomized algorithms to factor polynomials, and can also be used as a preprocessing step before Berlekamp’s algorithm. Algorithm 3 briefly describes how it works.
We implement the algorithm in Isabelle/HOL as
. Termination follows from the fact that difference between d and the degree of v decreases in every iteration. The key to the soundness of the algorithm is the fact that any irreducible polynomial f of degree d divides the polynomial \(x^{p^d} - x\) and does not divide \(x^{p^c}-x\) for \(1 \le c < d\). The corresponding Isabelle’s statement looks as follows where the polynomial x is encoded as
, i.e., \(1 \cdot x^1\).
Lemma 17
Knuth presents such a property as a consequence of an exercise in his book, whose proof is sketched in prose in just 5 lines [18, Exercise 4.6.2.16]. In comparison, our Isabelle proof required more effort: it took us about 730 lines, above all because we proved several facts and subproblems:Footnote 6
Given a degree-n irreducible polynomial \(f \in \mathrm {GF}(p)[x]\), the \(p^n\) polynomials of degree less than n form a field under arithmetic modulo f and p.
Any field with \(p^n\) elements has a generator element \(\xi \) such that the elements of the field are \(\{0,1,\xi , \xi ^2, \dots , \xi ^{p^n-2}\}\). We do not follow Knuth’s short argument in this step, but we reuse some theorems of the Isabelle library to provide a proof based on the existence of an element in the multiplicative group of the finite field with the adequate order.
Given a degree-n irreducible polynomial \(f \in \mathrm {GF}(p)[x]\), \(x^{p^m} - x\) is divisible by f if and only if m is a multiple of n. Essentially, we are proving that \(\mathrm {GF}(p^n)\) is a subfield of \(\mathrm {GF}(p^m)\) if and only if n divides m.
The difference between the sizes of Knuth’s and our proofs is also due to some properties which Knuth leaves as exercises. For instance, we show that \(a^{p^n} = a\) for any element \(a\in \mathrm {GF}(p)\), also that \((f+g)^{p^n} = f^{p^n} + g^{p^n}\) in the ring \(\mathrm {GF}(p)[x]\), for natural numbers \(x>1\), \(a>0\) and \(b>0\) we demonstrate
and some other properties like these ones which cause the increase in the number of employed lines. The whole formalization of these facts, the termination-proof of the algorithm and its soundness can be seen in the file Distinct_Degree_Factorization.thy of our development.
Once we have the distinct-degree factorization formalized, it remains to find a way to split each factor that we have found into the desired irreducible factors, but this can just be done by means of the Berlekamp’s algorithm. This way, we have two ways of factoring polynomials in \(\mathrm {GF}(p)[x]\):
We verified both variants as a single function
where a Boolean constant is used to enable or disable the preprocessing via distinct-degree factorization. Our experiments revealed that currently the preprocessing slows down the factorization algorithm, so the value of the Boolean constant is set to disable the preprocessing. However, since distinct degree factorization heavily depends on polynomial multiplication, the preprocessing might pay off, once more efficient polynomial multiplication algorithms become available in Isabelle.
Independent of the value of the Boolean constant, the final type-based statement for the soundness of
is as follows.
Theorem 4
(Finite Field Factorization)
Here,
converts a list into a multiset, and
demands that the given factorization is the unique factorization of f, i.e., c is the leading coefficient of f and \( fs \) a list of irreducible and monic factors such that \(f = c \cdot {\prod \, fs }\). Uniqueness follows from the general theorem that the polynomials over fields form a unique factorization domain.
Implementing Finite Field Factorization
The soundness of Theorem 4 is formulated in a type-based setting. In particular, the function
has type
In our use case, recall that Algorithm 1 first computes a prime number p, and then invokes a factorization algorithm (such as Berlekamp’s algorithm) on \(\mathrm {GF}(p)\). This requires Algorithm 1 to construct a new type \(\tau \) with
depending on the value of p, and then invoke
for type
.
Unfortunately, this is not possible in Isabelle/HOL. Hence, Algorithm 1 requires a finite field factorization algorithm to have a type like
where the first argument is the dynamically chosen prime p.
The final goal is to prove Theorem 4 but just involving integers, integer polynomials and integer lists, and then avoiding statements and definitions that require anything of type
(or in general, anything involving the type
).
The solution is to follow the steps already detailed in Sect. 3. We briefly recall the main steps here:
As the approach is the same as the presented in Sect. 3, we omit here the details. We simply remark that the diagnostic commands
and
were helpful to see why certain transfer rules could initially not be proved automatically; these commands nicely pointed to missing transfer rules.
Most of the transfer rules for non-recursive algorithms were proved mainly by unfolding the definitions and finishing the proof by
. For recursive algorithms, we often perform induction via the algorithm. To handle an inductive case, we locally declare transfer rules (obtained from the induction hypothesis), unfold one function application iteration, and then finish the proof by
.
Still, problems arose in case of underspecification. For instance it is impossible to prove an unconditional transfer rule for the function
that returns the head of a list using the standard relator for lists,
; when the lists of type
and
are empty, we have to relate
with
. To circumvent this problem, we had to reprove invariants that
is invoked only on non-empty lists.
Similar problems arose when using matrix indices where transfer rules between matrix entries \(A_{ij}\) and \(B_{ij}\) are available only if i and j are within the matrix dimensions. So, again we had to reprove the invariants on valid indices—just unfolding the definition and invoking
was not sufficient.
Although there is some overhead in this approach—namely by copying the type-based algorithms into record-based ones, and by proving the transfer rules for each of the algorithms—it still simplifies the overall development: once this setup has been established, we can easily transfer statements about properties of the algorithms, without having to copy or adjust their proofs.
This way, we obtain a formalized and executable factorization algorithm for polynomials in finite fields where the prime number p can be determined at runtime, and where the arithmetic in \(\mathrm {GF}(p)\) is selected dynamically without the risk of integer overflow. The final theorem follows, which is the integer-based version of Theorem 4.
Theorem 5
(Finite Field Factorization on Integers)
In summary, the development of the separate implementation is some annoying overhead, but still a workable solution. In numbers: Theorem 4 requires around 4300 lines of difficult proofs whereas Theorem 5 demands around 600 lines of easy proofs.