Formalizing Size-Optimal Sorting Networks: Extracting a Certified Proof Checker

Since the proof of the four color theorem in 1976, computer-generated proofs have become a reality in mathematics and computer science. During the last decade, we have seen formal proofs using verified proof assistants being used to verify the validity of such proofs. In this paper, we describe a formalized theory of size-optimal sorting networks. From this formalization we extract a certified checker that successfully verifies computer-generated proofs of optimality on up to 8 inputs. The checker relies on an untrusted oracle to shortcut the search for witnesses on more than 1.6 million NP-complete subproblems.


Introduction
Sorting networks are hardware-oriented algorithms to sort a fixed number of inputs using a predetermined sequence of comparisons between them. They are built from a primitive operator -the comparator -, which reads the values on two channels, and interchanges them if necessary to guarantee that the smallest one is always on a predetermined channel. Comparisons between independent pairs of values can be performed in parallel, and the two main optimization problems one wants to addressed are: how many comparators do we need to sort n inputs (the optimal size problem); and how many computation steps do we need to sort n inputs (the optimal depth problem).
So far, most results obtained on these two problems require exhaustive analysis of huge space states. For example, in order to prove that the known sorting network of size 25 on 9 inputs is optimal, one has to show that no sequence of 24 comparators will sort all sequences of 9 inputs. There are several theoretical results that help reduce the full search space of over 10 37 possibilities, but the resulting number of possibilities is still daunting.
In previous work [6] we proposed a generate-and-prune algorithm to show size optimality of sorting networks, and used it to establish optimality of the 25-comparator sorting networks on 9 inputs. This program includes a pruning step that takes two sequences of comparators and decides whether one of them can be ignored; however, this requires iteration over all 9! permutations of 9 elements. This expensive step, which often fails, has to be repeated billions of times throughout the whole run; therefore, the total execution required more than 10 years of computational time, or around one month on a state-of-the-art parallel cluster able to run 288 threads simultaneously.
During execution, we took care to record the comparator sequences and permutations that allowed successful pruning steps. Using this log, the whole run could be replicated and independently validated in just a few hours of sequential computation by shortcutting the expensive search process. While this additional step increased our confidence in the result, there remain reasonable grounds to argue whether these results constitute a valid mathematical proof.
In this paper we describe a Coq formalization of the relevant theory of sorting networks, from which we extract a certified checker with the goal of confirming the validity of our result. In order to obtain feasible runtimes, we bypass the expensive search process in the extracted certified checker by means of an oracle providing the information required for the pruning steps. The checker takes a skeptical approach towards the oracle: if the oracle provides wrong information at any step, the checker ignores it. The oracle is implemented independently by reading the original log filento the data structures expected by the checker.
This paper focuses on the formalization of the theory underlying the checker. We discuss how we can exploit the constructiveness of the theory to simplify the formalization and identify the places where skepticism towards the oracle becomes relevant. Finally, the interactive process of formalization itself revealed minor gaps in the hand-written proofs of [6], underlining the importance of formal proof assistants in computer-aided mathematical proofs. This paper is structured as follows. Section 2 summarizes the theory of sorting networks relevant for this formalization, and describes the generate-and-prune algorithm together with the information logged during its execution. Section 3 describes the formalization of the theory, with emphasis on the challenges encountered. Section 4 deals with the aspects of the formalization that have a direct impact on the extracted program, namely the specification of the oracle and the robustness needed to guarantee that unsound oracles do not compromise the final results. Section 5 addresses the implementation of the oracle and the execution of the extracted code. Finally, Section 6 presents some concluding remarks and directions in which this work can be extended.

Related work
The proof of the four colour theorem from 1976 [1,2] was not the first computerassisted proof, but it was the first to generate broad awareness of a new area of mathematics, sometimes dubbed "experimental" or "computational" mathematics. Since then, numerous theorems in mathematics and computer science have been proved by computer-assisted and computer-generated proofs. Besides obvious philosophical debates about what constitutes a mathematical proof, concerns about the validity of such proofs have been raised since. In particular, proofs based on exhausting the solution space have been met with skepticism.
During the last decade, we have seen an increasing use of verified proof assistants to create formally verified computer-generated proofs. This has been a success story, and it has resulted in a plethora of formalizations of mathematical proofs, a list too long to even start mentioning particular instances. Pars pro toto, consider the formal proof of the four colour theorem from 2005 [11].
Outside the world of formal proofs, computer-generated proofs are flourishing, too, and growing to tremendous sizes. The proof of Erdös' discrepancy conjecture for C = 2 from 2014 [13] has been touted as one of the largest mathematical proofs and produced approx. 13 GB of proof witnesses. Such large-scale proofs are extremely challenging for formal verification. Given the current state of theorem provers and computing equipment, it is unthinkable to use Claret et al.'s approach [5] of importing an oracle based on the proof witnesses into Coq, a process clearly prohibitive for such large-scale proofs as we consider.
The last years have seen the appearance of untrusted oracles, e.g. for a verified compiler [14] or for polyhedral analysis [10]. Here, the verified proof tool is relegated to a checker of the computations of the untrusted oracle, e.g., by using hand-written untrusted code to compute a result and verified (extracted) code to check it before continuing the computation.
The termination proof certification projects IsaFoR/CeTA [17], based on Isabelle/HOL, and A3PAT [7], based on Coq, go one step further, and use an offline untrusted oracle approach, where different termination analyzers provide proof witnesses, which are stored and later checked. However, a typical termination proof has 10-100 proof witnesses and totals a few KB to a few MB of data, and recent work [16] mentions problems were encountered when dealing with proofs using "several hundred megabytes" of oracle data. In contrast, our target proof of size-optimality of sorting networks with 9 inputs requires dealing with nearly 70 million proof witnesses, totalling 27 GB of oracle data.

Background
A comparator network C with n channels and size k is a sequence of comparators C = (i 1 , j 1 ); . . . ; (i k , j k ), where each comparator (i , j ) is a pair of channels 1 ≤ i < j ≤ n. If C 1 and C 2 are comparator networks with n channels, then C 1 ; C 2 denotes the comparator network obtained by concatenating C 1 and C 2 . An input x = x 1 . . . x n ∈ {0, 1} n propagates through C as follows: x 0 = x, and for 0 < ≤ k, x is the permutation of x −1 obtained by interchanging x −1 i and . The output of the network for input x is C(x) = x k , and outputs(C) = C(x) x ∈ {0, 1} n . The comparator network C is a sorting network if all elements of outputs(C) are sorted (in ascending order). The zero-one principle [12] implies that a sorting network also sorts sequences over any other totally ordered set, e.g. integers. Images

Optimal Size Sorting Networks
The optimal-size sorting network problem is about finding the smallest size, S(n), of a sorting network on n channels. In 1964, Floyd and Knuth presented sorting networks of optimal size for n ≤ 8 and proved their optimality [9]. Their proof required analyzing huge state spaces by means of a computer program, and the combinatorial explosion involved implied that there was no further progress on this problem in the next fifty years, until our proof that S(9) = 25 [6]. The best currently known upper and lower bounds for S(n) are given in the following table. Given an n channel comparator network C = (i 1 , j 1 ); . . . ; (i k , j k ) and a permutation π on {1, . . . , n}, π(C) is the sequence (π(i 1 ), π(j 1 )); . . . ; (π(i k ), π(j k )). Formally, π(C) is not a comparator network, but rather a generalized comparator network : a comparator network that may contain comparators (i, j) with i > j, which order their outputs in descending order instead of ascending. A generalized sorting network can always be transformed into a (standard) sorting network with the same size and depth by means of a procedure we will call standardization: if C = C 1 ; (i, j); C 2 is a generalized sorting network with C 1 standard and i > j, then standardizing C yields C 1 ; (j, i); C 2 , where C 2 is obtained by (i) interchanging i and j and (ii) standardizing the result. We write C 1 ≈ C 2 (C 1 is equivalent to C 2 ) iff there is a permutation π such that C 1 is obtained by standardizing π(C 2 ). The two networks (a) and (b) above are equivalent via the permutation (1 3)(2 4).

Lemma 1.
If C is a generalized sorting network, then standardizing C yields a sorting network.
The proof of this result, proposed as Exercise 5.3.4.16 in [12], is an induction proof that requires manipulating permutations and reasoning about the cardinality of outputs(C).

The generate-and-prune approach
Conceptually, one could inspect all n-channel comparator networks of size k oneby-one to determine if any of them is a sorting network. However, even for small n such a naive approach is combinatorically infeasible. There are n(n−1)/2 comparators on n channels, and hence (n(n − 1)/2) k networks with k comparators. For n = 9, aiming to prove that there does not exist a sorting network with 24 comparators would mean inspecting approximately 2.25 × 10 37 comparator networks. Moreover, checking whether a comparator network is a sorting network is known to be a co-NP complete problem [15].
In [6] we propose an alternative approach, generate-and-prune, which is driven just as the naive approach, but takes advantage of the abundance of symmetries in comparator networks, formalized via the notion of subsumption. Given two comparator networks on n channels C a and C b , we say that C a subsumes C b , and write C a C b , if there exists a permutation π such that π(outputs(C a )) ⊆ outputs(C b ). If we need to make π explicit, we will write C a ≤ π C b . Lemma 2 ( [6]). Let C a and C b be comparator networks on n channels, both of the same size, and such that C a C b . Then, if there exists a sorting network C b ; C of size k, there also exists a sorting network C a ; C of size k.
The proof of this result is constructive: under the hypotheses, the standardization of C a ; π −1 (C) is a sorting network. Again, this requires extensive manipulation of permutations and reasoning about the elements of outputs(C a ; π −1 (C)).
Lemma 2 implies that, when adding a next comparator in the naive approach, we do not need to consider all possible positions to place it. In particular, we can omit networks that are subsumed by others.
The generate-and-prune algorithm iteratively builds two sets R n k and N n k of n channel networks of size k. First, it initializes R n 0 to consist of a single element: the empty comparator network. Then, it repeatedly applies two types of steps, Generate and Prune, as follows.
1. Generate: Given R n k , construct N n k+1 by adding one comparator to each element of R n k in all possible ways. 2. Prune: Given N n k+1 , construct R n k+1 such that every element of N n k+1 is subsumed by an element of R n k+1 . The algorithm stops when a sorting network is found, which will make |R n k | = 1. To implement Prune, we loop on N n k and check whether the current network is subsumed by any of the previous ones; if this is the case, we ignore it. Otherwise, we add it to R n k and remove any networks already in this set that are subsumed by it. This yields a double loop N n k where at each iteration we need to find out whether a subsumption exists -which, in the worst case, requires looping through all n! permutations. For n = 9, the largest set N n k is N 9 15 , with over 18 million elements, and there are potentially 300 × 10 12 subsumptions to test.
These algorithms are straightforward to implement, test and debug. Our implementation from [6] written in Prolog and can be applied to reconstruct all of the known values for S(n) for n ≤ 6 in under an hour of computation on a single core and, after several optimizations and parallelization as described in [6], was able to obtain the new value of S(9).
Soundness of generate-and-prune follows from the observation that N n k (and R n k ) are complete for the optimal size sorting network problem on n channels: if there exists an optimal size sorting network on n channels, then there exists one of the form C; C for some C ∈ N n k (or C ∈ R n k ), for every k.

Checking the Proof using Proof Witnesses
Even though we proved all of the mathematical claims underlying the design of the generate-and-prune algorithm and carefully checked the correctness of our Prolog implementation, it is reasonable to question the validity of the final result. In [6] we turned to Barendregt and Wiedijk's de Bruijn criterion [3]: every computer-generated proof should be verifiable by an independent small program (a "checker"). We therefore augmented our code to produce a log file of successful subsumptions during execution, and implemented an independent Java verifier that was able to re-check the result without needing to replicate the expensive search steps in just over 6 hours of computational time. 1 However, we may again question the validity of the checker, and enter into an endless loop of validations. In this paper, we propose a different goal: obtain a correct-by-design checker by extracting it from a formalized proof of the theory of sorting networks. The reason for aiming at extracting a checker, rather than the full generate-and-prune algorithm, is that by using the log as an (untrusted) oracle we again gain a speedup of several orders of magnitude, as we completely avoid all the search steps.
In total, we have logged proof witnesses for approx. 70 million subsumptions, yielding a 27 GB log file. Developing a formalization allowing the extraction of an efficient checker that uses an untrusted oracle of this magnitude is an exciting challenge that, to the best of our knowledge, has not been tackled before. We proceed in two stages. First, we formalize the theory of optimal-size sorting networks directly following [12], including the new results from [15,6]. Then we implement generate-and-prune with an oracle in Coq, prove its soundness, and extract a certified checker.

Formalizing sorting networks
Formalizing the theory of sorting networks presents some challenges relating to the very finite nature of the domain. All the relevant notions are parameterized on the number n of inputs, and thus the domain for most concepts is the finite set {0, 1, . . . , n − 1}.
Directly working with this set in Coq is very cumbersome due to the ensuing omnipresence of proof terms -every number required as argument has to be accompanied by a proof that it is in the adequate range. Furthermore, these proof terms are completely trivial, since the order relations on natural numbers are all decidable. Therefore, we chose to define all relevant concepts in terms of natural numbers, and define additional properties specifying that particular instances fall in the appropriate range. For example, a comparator is simply defined as a pair of natural numbers: Definition comparator : Set := (prod nat nat). and we define with predicates stating that a particular comparator is a (standard) comparator on n channels: Likewise, the type CN of comparator networks is defined as list comparator, and there are predicates stating that a comparator network spans n channels, and that it is standard (which simply state that all comparators in the list have the corresponding comparator property).
Comparator networks act on binary sequences, and we define these as a dependent type, similar to Vector.
We then define two operations get and set, such that (get n s) returns the element (0 or 1) in position n of s, and (set n s k) sets position n of s to 0, if k is 0, and 1 otherwise. Setting an index larger than the length of a sequence leaves the sequence unchanged, while attempting to get the value in an index out of range returns 2. Since the context for the usage of these functions always ensures that these situations do not occur, these options are immaterial for the formalization.
A sequence is sorted if its first element is 0 and the remaining sequence is sorted, or if it consists entirely of 1s. Sequences propagate through comparator networks as expected; a sorting network is a comparator network that sorts all inputs. We also define an alternative characterization of sorting networks in terms of their sets of outputs and prove its equivalence to this one, but for space constraints we will not present it here.
A posteriori, this characterization is actually quite close to the corresponding mathematical definition: the comparator network {(0, 2); (2, 5)} is a network on 6 channels, but it is also a network on 9 or 11 channels, or indeed on n channels for any n ≥ 6. So this implementation option does not only make the formalization easier, but it is also a good model of the way we think about these objects.

Proof methodology
As discussed above, we completely separate between objects and proof terms. This option is dictated by the constructive nature of the theory of sorting networks. The key results underlying the pruning step of the generate-and-prune algorithm are all of the form If there is a sorting network N , then there is another sorting network N such that. . . and the published proofs of these results [6,12,15] all proceed by explicitly describing how to construct N from N . We formalize these results as operators in order to simplify their reuse: instead of proving statements of the form ∀N.ϕ(N ) → ∃N .ψ(N ) we first define some transformation T and prove that ∀N.ϕ(N ) → ψ(T (N )) from which we can straightforwardly prove the original statement.
Keeping the proof terms separated from the definitions and formalizing existential proofs as operators has several advantages: it is much easier to define these operators and then prove that they satisfy the required properties than including proof terms in their definition; the hypotheses underlying the properties themselves become much more explicit -e.g. renumbering channels yields a network on the same number of channels and of the same size, and these two results are independent; later, we can use the operators directly together with the relevant lemmas, rather than repeatedly applying inversion on an existential statement; additional properties of the operators that are needed later are easy to add as new lemmas, instead of requiring changes to the original theorem; we automatically get proof irrelevance, as proof terms are universally quantified in lemmas.
As an example, recall the definition of standardization: given a comparator network C, pick the first comparator (i, j) for which i > j, replace it with (j, i) and exchange i with j in all subsequent comparators, then iterate the process until a fixpoint is reached. Standardization is the key ingredient in Lemma 2, and it is formalized using well-founded recursion as follows. We then prove that standardizing a comparator network on n channels yields a standard comparator network on n channels. This is not completely trivial, because of the permutation in the recursive step: permuting channel labels x and y preserves the total number channels n only if x < n and y < n. While these hypotheses trivially hold (x and y are channels in an n-channel network), requiring the corresponding proof terms in the definition of comparator would make the definition of std unreadable. In later results, we can use the std operator when needed. There are in total seven different properties that are needed in different places in the formalization, and all but two are proven independently. If we did not have std as an operator, they would have to be formalized together as one gigantic result stating that for every network C there exists another network C satisfying the seven necessary properties.

Permutations
Permutations are an essential part of the formalization, as they are used extensively in the proof of Lemma 2.
Representing permutations in Coq is a challenging problem, and there are several common alternatives. The standard library includes an inductive type stating that two lists are permutations of each other; but manipulating it is cumbersome. Furthermore, we are not interested in developing a theory of permutations, but rather in proving results about comparator networks whose channels are renamed by means of a permutation of the numbers 0, . . . , n − 1, which we will hereafter refer to as "a permutation of [n]". Therefore we want a definition that makes it easy and efficient to apply permutations to objects.
For this reason, we chose to represent permutations as finite functions. A permutation P is a list of pairs of natural numbers, with the intended meaning that (i, j) ∈ P corresponds to P mapping i into j. We assume that P does not change i if there is no pair (i, j) ∈ P -this makes it much simpler to represent transpositions, which are the only permutations we need to represent explicitly in the formalization. In order for P to be a valid permutation of [n], several conditions have to hold: 1. all pairs (i, j) ∈ P must satisfy i < n and j < n; 2. no number may occur twice either as the first or as the second element of distinct pairs in P ; and 3. the sets of numbers occuring as first or second elements of the pairs in P must coincide.
As before, we separate the datatype of permutations from the property of being a permutation. Here, NoDup is the Coq standard library predicate stating that a list does not have duplicate elements, and all_lt(n,l) is an inductive predicate stating that all elements of l are smaller than n. As a sanity-check, we prove the relationship with the permutations in the Coq standard library.
All properties of permutations are added to the core hint database, so that Coq can automatically prove most properties of permutations required during the formalization.
We provide mechanisms to define permutations in four different ways, three of which correspond to the usage of permutations in proofs, and another one which will be necessary for interacting with the oracle. The former are as follows.
1. The identity permutation is simply the empty list, and it is easily shown to be a permutation of [n] for any n. 2. Given a permutation P, we construct its inverse (inverse_perm P) by reversing all pairs in P. If P is a permutation of [n], then so is (inverse_perm P).

The transposition (transposition i j) is the permutation that switches
i and j, leaving all other values unchanged. This transposition is defined as the list {(i, j), (j, i)}, and in order for it to be a permutation it is necessary that i = j (otherwise the list {i, j} contains duplicate elements). This condition therefore shows up in some results about transpositions; it is never a problem, though, as all transpositions arise from the standardization function, where i and j are obtained from a comparator (i, j).
We also need to get permutations from the oracle, and here we use a different representation for efficiency reasons. The log files record permutations as their output on the set [n], so for example the transposition over [4] exchanging 0 and 2 would be represented as {2, 1, 0, 3}. Since we want to be skeptic about the oracle, we do not assume anything about the lists we are given; rather, we show that the property of a list of natural numbers corresponding to a permutation on [n] is decidable. We then define a function make_perm to translate lists of natural numbers into (syntactic) permutations, and show that the resulting object satisfies permutation if the original list corresponds to a permutation. Thus, our checker will be able to get a list of natural numbers from the oracle, test whether it corresponds to a permutation, and in the affirmative case use this information.
One might wonder whether we could not have represented permutations uniformly throughout. The reason for not doing so is that we have two distinct objectives in mind. While formalizing results, we are working with an unknown number n of channels, and it is much simpler to represent permutations by only explicitly mentioning the values that are changed, as this allows for uniform representations of transpositions and the identity permutation. Also, computing the inverse of a permutation is very simple with the finite function representation, but not from the compact list representation given by the oracle. When running the extracted checker, however, we are concerned with efficiency. The oracle will provide information on millions of subsumptions, so it is of the utmost importance to minimize its size.

Formalizing generate-and-prune
Soundness of generate-and-prune algorithm relies on the notion of a complete set of filters. When formalizing this concept, we needed to make two changes: the element C of R being extended must be a standard comparator network with no redundant comparators 2 ; and (as a consequence) the size of the sorting network extending C is at most k, since there is an upper bound on how many non-redundant comparisons we can make on n inputs. These changes were discovered during the formalization of the original soundness proof [6], which implictly used on the fact that the elements of the complete sets of filters constructed were not redundant.
We prove that the set {∅} is complete, and that if there is a complete set of filters R whose elements all have size k, then all sorting networks on n channels The full Coq formalization and its generated documentation are available from http://imada.sdu.dk/~{}petersk/sn/

Running the extracted program
We extracted the certified checker to Haskell using Coq's extraction mechanism. The result is a file Checker.hs containing among others a Haskell function generate_and_Prune :: Nat -> Nat -> (List Oracle) -> Answer. In order to run this extracted certified checker, we wrote a Haskell interface that calls generate_and_Prune function with the number of channels, the maximum size of the networks, and the list of the oracle information, and then prints the answer. This interface includes conversion functions from Haskell integers to the extracted naturals and a function implementing the oracle, as well as a definition of Checker.Answer to be an instance of the type class Show for printing the result.
It is important to stress that we do not need to worry about soundness of almost any function defined in the interface, as the oracle is untrusted. For example, a wrong conversion from natural numbers to their Peano representation will not impact the correctness of the execution (although it will definitely impact the execution time, as all subsumptions will become invalid). We only need to worry about the function printing the result, but this is straightforward to verify.
The extracted checker was able to validate the proofs of optimal size up to and including n = 8 in around one day -roughly the same time it took to produce the original proof, albeit without search. This required processing more than 300 MB of proof witnesses for the roughly 1.6 million subsumptions. To the best of our knowledge, it constitutes the first formal proof of the results in [9]. Experiments suggested that the verification of the proof that S(9) = 25 would take around 20 years.

Conclusions
We have have presented a formalization of the theory of size-optimal sorting networks, extracted a verified checker for size-optimality proofs, and used it to show that informal results obtained in previous work are correct.
Our main contribution is a formalization of the theory of size-optimal sorting networks, including an intuitive and reusable formalization of comparator networks and a new representation of permutations more suitable for computation.
Another immediate contribution is a certified checker that directly confirmed all the values of S(n) quoted in [9].
Subsequently, we focused on making the checker more efficient without changing the formalization described in this paper [8]. This eventually allowed us to verify also the claim that S(9) = 25. We plan to apply the same techniquefirst formalize, then optimize -to other computer-generated proofs where formal verification has been prohibitively expensive so far.